Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: wacom - add support for new USB Tablet PCs Input: replace spin_lock_bh with spin_lock_irqsave in ml_ff_playback Input: i8042 - add Compal Hel80 laptop to nomux blacklist Input: cm109 - add keymap for ATCom AU-100 phone Input: fix the example of an input device driver Input: psmouse - fix incorrect validate_byte check in OLPC protocol Input: atkbd - cancel delayed work before freeing its structure Input: atkbd - add keymap quirk for Inventec Symphony systems Input: i8042 - add Dell XPS M1530 to nomux list Input: elo - fix format string in elo driver
This commit is contained in:
commit
b31a0fecd1
10 changed files with 436 additions and 54 deletions
|
@ -20,10 +20,11 @@ pressed or released a BUTTON_IRQ happens. The driver could look like:
|
|||
|
||||
static struct input_dev *button_dev;
|
||||
|
||||
static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
|
||||
static irqreturn_t button_interrupt(int irq, void *dummy)
|
||||
{
|
||||
input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1);
|
||||
input_sync(button_dev);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __init button_init(void)
|
||||
|
|
|
@ -824,7 +824,7 @@ static void atkbd_disconnect(struct serio *serio)
|
|||
atkbd_disable(atkbd);
|
||||
|
||||
/* make sure we don't have a command in flight */
|
||||
flush_scheduled_work();
|
||||
cancel_delayed_work_sync(&atkbd->event_work);
|
||||
|
||||
sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
|
||||
input_unregister_device(atkbd->dev);
|
||||
|
@ -867,6 +867,22 @@ static void atkbd_hp_keymap_fixup(struct atkbd *atkbd)
|
|||
atkbd->force_release_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
* Inventec system with broken key release on volume keys
|
||||
*/
|
||||
static void atkbd_inventec_keymap_fixup(struct atkbd *atkbd)
|
||||
{
|
||||
const unsigned int forced_release_keys[] = {
|
||||
0xae, 0xb0,
|
||||
};
|
||||
int i;
|
||||
|
||||
if (atkbd->set == 2)
|
||||
for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++)
|
||||
__set_bit(forced_release_keys[i],
|
||||
atkbd->force_release_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
* atkbd_set_keycode_table() initializes keyboard's keycode table
|
||||
* according to the selected scancode set
|
||||
|
@ -1468,6 +1484,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
|
|||
.callback = atkbd_setup_fixup,
|
||||
.driver_data = atkbd_hp_keymap_fixup,
|
||||
},
|
||||
{
|
||||
.ident = "Inventec Symphony",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"),
|
||||
},
|
||||
.callback = atkbd_setup_fixup,
|
||||
.driver_data = atkbd_inventec_keymap_fixup,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
static char *phone = "kip1000";
|
||||
module_param(phone, charp, S_IRUSR);
|
||||
MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01}");
|
||||
MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01, atcom}");
|
||||
|
||||
enum {
|
||||
/* HID Registers */
|
||||
|
@ -258,6 +258,37 @@ static unsigned short keymap_usbph01(int scancode)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Keymap for ATCom AU-100
|
||||
* http://www.atcom.cn/En_products_AU100.html
|
||||
* http://www.packetizer.com/products/au100/
|
||||
* http://www.voip-info.org/wiki/view/AU-100
|
||||
*
|
||||
* Contributed by daniel@gimpelevich.san-francisco.ca.us
|
||||
*/
|
||||
static unsigned short keymap_atcom(int scancode)
|
||||
{
|
||||
switch (scancode) { /* phone key: */
|
||||
case 0x82: return KEY_NUMERIC_0; /* 0 */
|
||||
case 0x11: return KEY_NUMERIC_1; /* 1 */
|
||||
case 0x12: return KEY_NUMERIC_2; /* 2 */
|
||||
case 0x14: return KEY_NUMERIC_3; /* 3 */
|
||||
case 0x21: return KEY_NUMERIC_4; /* 4 */
|
||||
case 0x22: return KEY_NUMERIC_5; /* 5 */
|
||||
case 0x24: return KEY_NUMERIC_6; /* 6 */
|
||||
case 0x41: return KEY_NUMERIC_7; /* 7 */
|
||||
case 0x42: return KEY_NUMERIC_8; /* 8 */
|
||||
case 0x44: return KEY_NUMERIC_9; /* 9 */
|
||||
case 0x84: return KEY_NUMERIC_POUND; /* # */
|
||||
case 0x81: return KEY_NUMERIC_STAR; /* * */
|
||||
case 0x18: return KEY_ENTER; /* pickup */
|
||||
case 0x28: return KEY_ESC; /* hangup */
|
||||
case 0x48: return KEY_LEFT; /* left arrow */
|
||||
case 0x88: return KEY_RIGHT; /* right arrow */
|
||||
default: return special_keymap(scancode);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned short (*keymap)(int) = keymap_kip1000;
|
||||
|
||||
/*
|
||||
|
@ -840,6 +871,10 @@ static int __init cm109_select_keymap(void)
|
|||
keymap = keymap_usbph01;
|
||||
printk(KERN_INFO KBUILD_MODNAME ": "
|
||||
"Keymap for Allied-Telesis Corega USBPH01 phone loaded\n");
|
||||
} else if (!strcasecmp(phone, "atcom")) {
|
||||
keymap = keymap_atcom;
|
||||
printk(KERN_INFO KBUILD_MODNAME ": "
|
||||
"Keymap for ATCom AU-100 phone loaded\n");
|
||||
} else {
|
||||
printk(KERN_ERR KBUILD_MODNAME ": "
|
||||
"Unsupported phone: %s\n", phone);
|
||||
|
|
|
@ -125,7 +125,7 @@ static void hgpk_spewing_hack(struct psmouse *psmouse,
|
|||
*/
|
||||
static int hgpk_validate_byte(unsigned char *packet)
|
||||
{
|
||||
return (packet[0] & 0x0C) == 0x08;
|
||||
return (packet[0] & 0x0C) != 0x08;
|
||||
}
|
||||
|
||||
static void hgpk_process_packet(struct psmouse *psmouse)
|
||||
|
|
|
@ -337,6 +337,20 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "2656"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Dell XPS M1530",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Compal HEL80I",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
* - Support Intuos3 4x6
|
||||
* v1.47 (pc) - Added support for Bamboo
|
||||
* v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX
|
||||
* v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -86,7 +87,7 @@
|
|||
/*
|
||||
* Version Information
|
||||
*/
|
||||
#define DRIVER_VERSION "v1.48"
|
||||
#define DRIVER_VERSION "v1.49"
|
||||
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
|
||||
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
|
||||
#define DRIVER_LICENSE "GPL"
|
||||
|
@ -103,15 +104,15 @@ struct wacom {
|
|||
struct usb_device *usbdev;
|
||||
struct usb_interface *intf;
|
||||
struct urb *irq;
|
||||
struct wacom_wac * wacom_wac;
|
||||
struct wacom_wac *wacom_wac;
|
||||
struct mutex lock;
|
||||
unsigned int open:1;
|
||||
char phys[32];
|
||||
};
|
||||
|
||||
struct wacom_combo {
|
||||
struct wacom * wacom;
|
||||
struct urb * urb;
|
||||
struct wacom *wacom;
|
||||
struct urb *urb;
|
||||
};
|
||||
|
||||
extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
|
||||
|
@ -132,7 +133,7 @@ extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wa
|
|||
extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
|
||||
extern __u16 wacom_le16_to_cpu(unsigned char *data);
|
||||
extern __u16 wacom_be16_to_cpu(unsigned char *data);
|
||||
extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
|
||||
extern const struct usb_device_id * get_device_table(void);
|
||||
extern struct wacom_features *get_wacom_feature(const struct usb_device_id *id);
|
||||
extern const struct usb_device_id *get_device_table(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,8 +14,41 @@
|
|||
#include "wacom.h"
|
||||
#include "wacom_wac.h"
|
||||
|
||||
/* defines to get HID report descriptor */
|
||||
#define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01)
|
||||
#define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02)
|
||||
#define HID_USAGE_UNDEFINED 0x00
|
||||
#define HID_USAGE_PAGE 0x05
|
||||
#define HID_USAGE_PAGE_DIGITIZER 0x0d
|
||||
#define HID_USAGE_PAGE_DESKTOP 0x01
|
||||
#define HID_USAGE 0x09
|
||||
#define HID_USAGE_X 0x30
|
||||
#define HID_USAGE_Y 0x31
|
||||
#define HID_USAGE_X_TILT 0x3d
|
||||
#define HID_USAGE_Y_TILT 0x3e
|
||||
#define HID_USAGE_FINGER 0x22
|
||||
#define HID_USAGE_STYLUS 0x20
|
||||
#define HID_COLLECTION 0xc0
|
||||
|
||||
enum {
|
||||
WCM_UNDEFINED = 0,
|
||||
WCM_DESKTOP,
|
||||
WCM_DIGITIZER,
|
||||
};
|
||||
|
||||
struct hid_descriptor {
|
||||
struct usb_descriptor_header header;
|
||||
__le16 bcdHID;
|
||||
u8 bCountryCode;
|
||||
u8 bNumDescriptors;
|
||||
u8 bDescriptorType;
|
||||
__le16 wDescriptorLength;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* defines to get/set USB message */
|
||||
#define USB_REQ_GET_REPORT 0x01
|
||||
#define USB_REQ_SET_REPORT 0x09
|
||||
#define WAC_HID_FEATURE_REPORT 0x03
|
||||
|
||||
static int usb_get_report(struct usb_interface *intf, unsigned char type,
|
||||
unsigned char id, void *buf, int size)
|
||||
|
@ -80,25 +113,21 @@ static void wacom_sys_irq(struct urb *urb)
|
|||
void wacom_report_key(void *wcombo, unsigned int key_type, int key_data)
|
||||
{
|
||||
input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data);
|
||||
return;
|
||||
}
|
||||
|
||||
void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data)
|
||||
{
|
||||
input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data);
|
||||
return;
|
||||
}
|
||||
|
||||
void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data)
|
||||
{
|
||||
input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data);
|
||||
return;
|
||||
}
|
||||
|
||||
void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value)
|
||||
{
|
||||
input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value);
|
||||
return;
|
||||
}
|
||||
|
||||
__u16 wacom_be16_to_cpu(unsigned char *data)
|
||||
|
@ -118,7 +147,6 @@ __u16 wacom_le16_to_cpu(unsigned char *data)
|
|||
void wacom_input_sync(void *wcombo)
|
||||
{
|
||||
input_sync(get_input_dev((struct wacom_combo *)wcombo));
|
||||
return;
|
||||
}
|
||||
|
||||
static int wacom_open(struct input_dev *dev)
|
||||
|
@ -160,7 +188,7 @@ static void wacom_close(struct input_dev *dev)
|
|||
|
||||
void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
||||
{
|
||||
input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_1) |
|
||||
input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_1) |
|
||||
BIT_MASK(BTN_5);
|
||||
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
|
||||
}
|
||||
|
@ -170,7 +198,7 @@ void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
|||
input_dev->evbit[0] |= BIT_MASK(EV_MSC);
|
||||
input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
|
||||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
|
||||
input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) |
|
||||
input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) |
|
||||
BIT_MASK(BTN_4);
|
||||
}
|
||||
|
||||
|
@ -178,7 +206,7 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
|||
{
|
||||
input_dev->evbit[0] |= BIT_MASK(EV_REL);
|
||||
input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
|
||||
input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
|
||||
input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) |
|
||||
BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
|
||||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
|
||||
BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2);
|
||||
|
@ -188,7 +216,7 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
|||
void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
||||
{
|
||||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
|
||||
input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) |
|
||||
input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) |
|
||||
BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3);
|
||||
input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
|
||||
|
@ -196,14 +224,14 @@ void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
|||
|
||||
void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
||||
{
|
||||
input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_4) |
|
||||
input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) |
|
||||
BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7);
|
||||
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
|
||||
}
|
||||
|
||||
void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
||||
{
|
||||
input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9);
|
||||
input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9);
|
||||
}
|
||||
|
||||
void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
||||
|
@ -211,7 +239,7 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
|||
input_dev->evbit[0] |= BIT_MASK(EV_MSC) | BIT_MASK(EV_REL);
|
||||
input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
|
||||
input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
|
||||
input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
|
||||
input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) |
|
||||
BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) |
|
||||
BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
|
||||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
|
||||
|
@ -228,8 +256,7 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
|||
|
||||
void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
||||
{
|
||||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2) |
|
||||
BIT_MASK(BTN_TOOL_RUBBER);
|
||||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2);
|
||||
}
|
||||
|
||||
void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
||||
|
@ -237,15 +264,129 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
|||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER);
|
||||
}
|
||||
|
||||
static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
|
||||
struct wacom_wac *wacom_wac)
|
||||
{
|
||||
struct usb_device *dev = interface_to_usbdev(intf);
|
||||
struct wacom_features *features = wacom_wac->features;
|
||||
char limit = 0, result = 0;
|
||||
int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
|
||||
unsigned char *report;
|
||||
|
||||
report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
|
||||
if (!report)
|
||||
return -ENOMEM;
|
||||
|
||||
/* retrive report descriptors */
|
||||
do {
|
||||
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_RECIP_INTERFACE | USB_DIR_IN,
|
||||
HID_DEVICET_REPORT << 8,
|
||||
intf->altsetting[0].desc.bInterfaceNumber, /* interface */
|
||||
report,
|
||||
hid_desc->wDescriptorLength,
|
||||
5000); /* 5 secs */
|
||||
} while (result < 0 && limit++ < 5);
|
||||
|
||||
if (result < 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < hid_desc->wDescriptorLength; i++) {
|
||||
|
||||
switch (report[i]) {
|
||||
case HID_USAGE_PAGE:
|
||||
switch (report[i + 1]) {
|
||||
case HID_USAGE_PAGE_DIGITIZER:
|
||||
usage = WCM_DIGITIZER;
|
||||
i++;
|
||||
break;
|
||||
|
||||
case HID_USAGE_PAGE_DESKTOP:
|
||||
usage = WCM_DESKTOP;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_USAGE:
|
||||
switch (report[i + 1]) {
|
||||
case HID_USAGE_X:
|
||||
if (usage == WCM_DESKTOP) {
|
||||
if (finger) {
|
||||
features->touch_x_max =
|
||||
features->touch_y_max =
|
||||
wacom_le16_to_cpu(&report[i + 3]);
|
||||
features->x_max =
|
||||
wacom_le16_to_cpu(&report[i + 6]);
|
||||
i += 7;
|
||||
} else if (pen) {
|
||||
features->x_max =
|
||||
wacom_le16_to_cpu(&report[i + 3]);
|
||||
i += 4;
|
||||
}
|
||||
} else if (usage == WCM_DIGITIZER) {
|
||||
/* max pressure isn't reported
|
||||
features->pressure_max = (unsigned short)
|
||||
(report[i+4] << 8 | report[i + 3]);
|
||||
*/
|
||||
features->pressure_max = 255;
|
||||
i += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_USAGE_Y:
|
||||
if (usage == WCM_DESKTOP)
|
||||
features->y_max =
|
||||
wacom_le16_to_cpu(&report[i + 3]);
|
||||
i += 4;
|
||||
break;
|
||||
|
||||
case HID_USAGE_FINGER:
|
||||
finger = 1;
|
||||
i++;
|
||||
break;
|
||||
|
||||
case HID_USAGE_STYLUS:
|
||||
pen = 1;
|
||||
i++;
|
||||
break;
|
||||
|
||||
case HID_USAGE_UNDEFINED:
|
||||
if (usage == WCM_DESKTOP && finger) /* capacity */
|
||||
features->pressure_max =
|
||||
wacom_le16_to_cpu(&report[i + 3]);
|
||||
i += 4;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_COLLECTION:
|
||||
/* reset UsagePage ans Finger */
|
||||
finger = usage = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result = 0;
|
||||
|
||||
out:
|
||||
kfree(report);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct usb_device *dev = interface_to_usbdev(intf);
|
||||
struct usb_host_interface *interface = intf->cur_altsetting;
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
struct wacom *wacom;
|
||||
struct wacom_wac *wacom_wac;
|
||||
struct wacom_features *features;
|
||||
struct input_dev *input_dev;
|
||||
int error = -ENOMEM;
|
||||
char rep_data[2], limit = 0;
|
||||
struct hid_descriptor *hid_desc;
|
||||
|
||||
wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
|
||||
wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
|
||||
|
@ -268,8 +409,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
|||
usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
|
||||
strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
|
||||
|
||||
wacom_wac->features = get_wacom_feature(id);
|
||||
BUG_ON(wacom_wac->features->pktlen > 10);
|
||||
wacom_wac->features = features = get_wacom_feature(id);
|
||||
BUG_ON(features->pktlen > 10);
|
||||
|
||||
input_dev->name = wacom_wac->features->name;
|
||||
wacom->wacom_wac = wacom_wac;
|
||||
|
@ -282,18 +423,37 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
|||
input_dev->open = wacom_open;
|
||||
input_dev->close = wacom_close;
|
||||
|
||||
endpoint = &intf->cur_altsetting->endpoint[0].desc;
|
||||
|
||||
/* TabletPC need to retrieve the physical and logical maximum from report descriptor */
|
||||
if (wacom_wac->features->type == TABLETPC) {
|
||||
if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
|
||||
if (usb_get_extra_descriptor(&interface->endpoint[0],
|
||||
HID_DEVICET_REPORT, &hid_desc)) {
|
||||
printk("wacom: can not retrive extra class descriptor\n");
|
||||
goto fail2;
|
||||
}
|
||||
}
|
||||
error = wacom_parse_hid(intf, hid_desc, wacom_wac);
|
||||
if (error)
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
|
||||
BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS);
|
||||
input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0);
|
||||
input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0);
|
||||
input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0);
|
||||
if (features->type == TABLETPC) {
|
||||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
|
||||
input_set_abs_params(input_dev, ABS_RX, 0, features->touch_x_max, 4, 0);
|
||||
input_set_abs_params(input_dev, ABS_RY, 0, features->touch_y_max, 4, 0);
|
||||
}
|
||||
input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
|
||||
|
||||
wacom_init_input_dev(input_dev, wacom_wac);
|
||||
|
||||
endpoint = &intf->cur_altsetting->endpoint[0].desc;
|
||||
|
||||
usb_fill_int_urb(wacom->irq, dev,
|
||||
usb_rcvintpipe(dev, endpoint->bEndpointAddress),
|
||||
wacom_wac->data, wacom_wac->features->pktlen,
|
||||
|
@ -305,13 +465,22 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
|||
if (error)
|
||||
goto fail3;
|
||||
|
||||
/* Ask the tablet to report tablet data. Repeat until it succeeds */
|
||||
do {
|
||||
rep_data[0] = 2;
|
||||
rep_data[1] = 2;
|
||||
usb_set_report(intf, 3, 2, rep_data, 2);
|
||||
usb_get_report(intf, 3, 2, rep_data, 2);
|
||||
} while (rep_data[1] != 2 && limit++ < 5);
|
||||
/*
|
||||
* Ask the tablet to report tablet data if it is not a Tablet PC.
|
||||
* Repeat until it succeeds
|
||||
*/
|
||||
if (wacom_wac->features->type != TABLETPC) {
|
||||
do {
|
||||
rep_data[0] = 2;
|
||||
rep_data[1] = 2;
|
||||
error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
|
||||
2, rep_data, 2);
|
||||
if (error >= 0)
|
||||
error = usb_get_report(intf,
|
||||
WAC_HID_FEATURE_REPORT, 2,
|
||||
rep_data, 2);
|
||||
} while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
|
||||
}
|
||||
|
||||
usb_set_intfdata(intf, wacom);
|
||||
return 0;
|
||||
|
@ -333,7 +502,8 @@ static void wacom_disconnect(struct usb_interface *intf)
|
|||
usb_kill_urb(wacom->irq);
|
||||
input_unregister_device(wacom->dev);
|
||||
usb_free_urb(wacom->irq);
|
||||
usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
|
||||
usb_buffer_free(interface_to_usbdev(intf), 10,
|
||||
wacom->wacom_wac->data, wacom->data_dma);
|
||||
kfree(wacom->wacom_wac);
|
||||
kfree(wacom);
|
||||
}
|
||||
|
|
|
@ -535,31 +535,147 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
|
||||
{
|
||||
char *data = wacom->data;
|
||||
int prox = 0, pressure;
|
||||
static int stylusInProx, touchInProx = 1, touchOut;
|
||||
struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
|
||||
|
||||
dbg("wacom_tpc_irq: received report #%d", data[0]);
|
||||
|
||||
if (urb->actual_length == 5 || data[0] == 6) { /* Touch data */
|
||||
if (urb->actual_length == 5) { /* with touch */
|
||||
prox = data[0] & 0x03;
|
||||
} else { /* with capacity */
|
||||
prox = data[1] & 0x03;
|
||||
}
|
||||
|
||||
if (!stylusInProx) { /* stylus not in prox */
|
||||
if (prox) {
|
||||
if (touchInProx) {
|
||||
wacom->tool[1] = BTN_TOOL_DOUBLETAP;
|
||||
wacom->id[0] = TOUCH_DEVICE_ID;
|
||||
if (urb->actual_length != 5) {
|
||||
wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
|
||||
wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
|
||||
wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
|
||||
wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
|
||||
} else {
|
||||
wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
|
||||
wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
|
||||
wacom_report_key(wcombo, BTN_TOUCH, 1);
|
||||
}
|
||||
wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
|
||||
wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
|
||||
touchOut = 1;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
|
||||
wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
|
||||
wacom_report_key(wcombo, BTN_TOUCH, 0);
|
||||
touchOut = 0;
|
||||
touchInProx = 1;
|
||||
return 1;
|
||||
}
|
||||
} else if (touchOut || !prox) { /* force touch out-prox */
|
||||
wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
|
||||
wacom_report_key(wcombo, BTN_TOUCH, 0);
|
||||
touchOut = 0;
|
||||
touchInProx = 1;
|
||||
return 1;
|
||||
}
|
||||
} else if (data[0] == 2) { /* Penabled */
|
||||
prox = data[1] & 0x20;
|
||||
|
||||
touchInProx = 0;
|
||||
|
||||
wacom->id[0] = ERASER_DEVICE_ID;
|
||||
|
||||
/*
|
||||
* if going from out of proximity into proximity select between the eraser
|
||||
* and the pen based on the state of the stylus2 button, choose eraser if
|
||||
* pressed else choose pen. if not a proximity change from out to in, send
|
||||
* an out of proximity for previous tool then a in for new tool.
|
||||
*/
|
||||
if (prox) { /* in prox */
|
||||
if (!wacom->tool[0]) {
|
||||
/* Going into proximity select tool */
|
||||
wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
|
||||
if (wacom->tool[1] == BTN_TOOL_PEN)
|
||||
wacom->id[0] = STYLUS_DEVICE_ID;
|
||||
} else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) {
|
||||
/*
|
||||
* was entered with stylus2 pressed
|
||||
* report out proximity for previous tool
|
||||
*/
|
||||
wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
|
||||
wacom_report_key(wcombo, wacom->tool[1], 0);
|
||||
wacom_input_sync(wcombo);
|
||||
|
||||
/* set new tool */
|
||||
wacom->tool[1] = BTN_TOOL_PEN;
|
||||
wacom->id[0] = STYLUS_DEVICE_ID;
|
||||
return 0;
|
||||
}
|
||||
if (wacom->tool[1] != BTN_TOOL_RUBBER) {
|
||||
/* Unknown tool selected default to pen tool */
|
||||
wacom->tool[1] = BTN_TOOL_PEN;
|
||||
wacom->id[0] = STYLUS_DEVICE_ID;
|
||||
}
|
||||
wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
|
||||
wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
|
||||
wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
|
||||
wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
|
||||
pressure = ((data[7] & 0x01) << 8) | data[6];
|
||||
if (pressure < 0)
|
||||
pressure = wacom->features->pressure_max + pressure + 1;
|
||||
wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
|
||||
wacom_report_key(wcombo, BTN_TOUCH, pressure);
|
||||
} else {
|
||||
wacom_report_abs(wcombo, ABS_PRESSURE, 0);
|
||||
wacom_report_key(wcombo, BTN_STYLUS, 0);
|
||||
wacom_report_key(wcombo, BTN_STYLUS2, 0);
|
||||
wacom_report_key(wcombo, BTN_TOUCH, 0);
|
||||
}
|
||||
wacom_report_key(wcombo, wacom->tool[1], prox);
|
||||
wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
|
||||
stylusInProx = prox;
|
||||
wacom->tool[0] = prox;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
|
||||
{
|
||||
switch (wacom_wac->features->type) {
|
||||
case PENPARTNER:
|
||||
return (wacom_penpartner_irq(wacom_wac, wcombo));
|
||||
break;
|
||||
return wacom_penpartner_irq(wacom_wac, wcombo);
|
||||
|
||||
case PL:
|
||||
return (wacom_pl_irq(wacom_wac, wcombo));
|
||||
break;
|
||||
return wacom_pl_irq(wacom_wac, wcombo);
|
||||
|
||||
case WACOM_G4:
|
||||
case GRAPHIRE:
|
||||
case WACOM_MO:
|
||||
return (wacom_graphire_irq(wacom_wac, wcombo));
|
||||
break;
|
||||
return wacom_graphire_irq(wacom_wac, wcombo);
|
||||
|
||||
case PTU:
|
||||
return (wacom_ptu_irq(wacom_wac, wcombo));
|
||||
break;
|
||||
return wacom_ptu_irq(wacom_wac, wcombo);
|
||||
|
||||
case INTUOS:
|
||||
case INTUOS3S:
|
||||
case INTUOS3:
|
||||
case INTUOS3L:
|
||||
case CINTIQ:
|
||||
case WACOM_BEE:
|
||||
return (wacom_intuos_irq(wacom_wac, wcombo));
|
||||
break;
|
||||
return wacom_intuos_irq(wacom_wac, wcombo);
|
||||
|
||||
case TABLETPC:
|
||||
return wacom_tpc_irq(wacom_wac, wcombo);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -586,13 +702,15 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w
|
|||
/* fall through */
|
||||
case INTUOS3S:
|
||||
input_dev_i3s(input_dev, wacom_wac);
|
||||
/* fall through */
|
||||
case INTUOS:
|
||||
input_dev_i(input_dev, wacom_wac);
|
||||
break;
|
||||
case PL:
|
||||
case PTU:
|
||||
case TABLETPC:
|
||||
input_dev_pl(input_dev, wacom_wac);
|
||||
break;
|
||||
/* fall through */
|
||||
case PENPARTNER:
|
||||
input_dev_pt(input_dev, wacom_wac);
|
||||
break;
|
||||
|
@ -611,6 +729,7 @@ static struct wacom_features wacom_features[] = {
|
|||
{ "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 },
|
||||
{ "Wacom BambooFun 4x5", 9, 14760, 9225, 511, 63, WACOM_MO },
|
||||
{ "Wacom BambooFun 6x8", 9, 21648, 13530, 511, 63, WACOM_MO },
|
||||
{ "Wacom Bamboo1 Medium",8, 16704, 12064, 511, 63, GRAPHIRE },
|
||||
{ "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE },
|
||||
{ "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE },
|
||||
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE },
|
||||
|
@ -650,6 +769,10 @@ static struct wacom_features wacom_features[] = {
|
|||
{ "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ },
|
||||
{ "Wacom Cintiq 20WSX", 10, 86680, 54180, 1023, 63, WACOM_BEE },
|
||||
{ "Wacom Cintiq 12WX", 10, 53020, 33440, 1023, 63, WACOM_BEE },
|
||||
{ "Wacom DTU1931", 8, 37832, 30305, 511, 0, PL },
|
||||
{ "Wacom ISDv4 90", 8, 26202, 16325, 255, 0, TABLETPC },
|
||||
{ "Wacom ISDv4 93", 8, 26202, 16325, 255, 0, TABLETPC },
|
||||
{ "Wacom ISDv4 9A", 8, 26202, 16325, 255, 0, TABLETPC },
|
||||
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS },
|
||||
{ }
|
||||
};
|
||||
|
@ -665,6 +788,7 @@ static struct usb_device_id wacom_ids[] = {
|
|||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x19) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
|
||||
|
@ -704,18 +828,26 @@ static struct usb_device_id wacom_ids[] = {
|
|||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC7) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
|
||||
{ }
|
||||
};
|
||||
|
||||
const struct usb_device_id * get_device_table(void) {
|
||||
const struct usb_device_id * id_table = wacom_ids;
|
||||
const struct usb_device_id *get_device_table(void)
|
||||
{
|
||||
const struct usb_device_id *id_table = wacom_ids;
|
||||
|
||||
return id_table;
|
||||
}
|
||||
|
||||
struct wacom_features * get_wacom_feature(const struct usb_device_id * id) {
|
||||
struct wacom_features * get_wacom_feature(const struct usb_device_id *id)
|
||||
{
|
||||
int index = id - wacom_ids;
|
||||
struct wacom_features *wf = &wacom_features[index];
|
||||
|
||||
return wf;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#define WACOM_WAC_H
|
||||
|
||||
#define STYLUS_DEVICE_ID 0x02
|
||||
#define TOUCH_DEVICE_ID 0x03
|
||||
#define CURSOR_DEVICE_ID 0x06
|
||||
#define ERASER_DEVICE_ID 0x0A
|
||||
#define PAD_DEVICE_ID 0x0F
|
||||
|
@ -27,6 +28,7 @@ enum {
|
|||
CINTIQ,
|
||||
WACOM_BEE,
|
||||
WACOM_MO,
|
||||
TABLETPC,
|
||||
MAX_TYPE
|
||||
};
|
||||
|
||||
|
@ -38,6 +40,8 @@ struct wacom_features {
|
|||
int pressure_max;
|
||||
int distance_max;
|
||||
int type;
|
||||
int touch_x_max;
|
||||
int touch_y_max;
|
||||
};
|
||||
|
||||
struct wacom_wac {
|
||||
|
|
|
@ -262,7 +262,7 @@ static int elo_setup_10(struct elo *elo)
|
|||
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
|
||||
|
||||
printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, "
|
||||
"features: %x02x, controller: 0x%02x\n",
|
||||
"features: 0x%02x, controller: 0x%02x\n",
|
||||
elo_types[(packet[1] -'0') & 0x03],
|
||||
packet[5], packet[4], packet[3], packet[7]);
|
||||
|
||||
|
|
Loading…
Reference in a new issue