wacom_wac.c

来自「linux 内核源代码」· C语言 代码 · 共 711 行 · 第 1/2 页

C
711
字号
/* * drivers/input/tablet/wacom_wac.c * *  USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code * *//* * 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. */#include "wacom.h"#include "wacom_wac.h"static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo){	unsigned char *data = wacom->data;	switch (data[0]) {		case 1:			if (data[5] & 0x80) {				wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;				wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID;				wacom_report_key(wcombo, wacom->tool[0], 1);				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */				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_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127);				wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127));				wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40));			} else {				wacom_report_key(wcombo, wacom->tool[0], 0);				wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */				wacom_report_abs(wcombo, ABS_PRESSURE, -1);				wacom_report_key(wcombo, BTN_TOUCH, 0);			}			break;		case 2:			wacom_report_key(wcombo, BTN_TOOL_PEN, 1);			wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */			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_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127);			wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));			wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40));			break;		default:			printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]);			return 0;        }	return 1;}static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo){	unsigned char *data = wacom->data;	int prox, id, pressure;	if (data[0] != 2) {		dbg("wacom_pl_irq: received unknown report #%d", data[0]);		return 0;	}	prox = data[1] & 0x40;	id = ERASER_DEVICE_ID;	if (prox) {		pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));		if (wacom->features->pressure_max > 255)			pressure = (pressure << 1) | ((data[4] >> 6) & 1);		pressure += (wacom->features->pressure_max + 1) / 2;		/*		 * 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 (!wacom->tool[0]) {			/* Eraser bit set for DTF */			if (data[1] & 0x10)				wacom->tool[1] = BTN_TOOL_RUBBER;			else				/* Going into proximity select tool */				wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;		} else {			/* was entered with stylus2 pressed */			if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {				/* report out proximity for previous tool */				wacom_report_key(wcombo, wacom->tool[1], 0);				wacom_input_sync(wcombo);				wacom->tool[1] = BTN_TOOL_PEN;				return 0;			}		}		if (wacom->tool[1] != BTN_TOOL_RUBBER) {			/* Unknown tool selected default to pen tool */			wacom->tool[1] = BTN_TOOL_PEN;			id = STYLUS_DEVICE_ID;		}		wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */		wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */		wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));		wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));		wacom_report_abs(wcombo, ABS_PRESSURE, pressure);		wacom_report_key(wcombo, BTN_TOUCH, data[4] & 0x08);		wacom_report_key(wcombo, BTN_STYLUS, data[4] & 0x10);		/* Only allow the stylus2 button to be reported for the pen tool. */		wacom_report_key(wcombo, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));	} else {		/* report proximity-out of a (valid) tool */		if (wacom->tool[1] != BTN_TOOL_RUBBER) {			/* Unknown tool selected default to pen tool */			wacom->tool[1] = BTN_TOOL_PEN;		}		wacom_report_key(wcombo, wacom->tool[1], prox);	}	wacom->tool[0] = prox; /* Save proximity state */	return 1;}static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo){	unsigned char *data = wacom->data;	int id;	if (data[0] != 2) {		printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);		return 0;	}	if (data[1] & 0x04) {		wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20);		wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08);		id = ERASER_DEVICE_ID;	} else {		wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20);		wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);		id = STYLUS_DEVICE_ID;	}	wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */	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_STYLUS, data[1] & 0x02);	wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);	return 1;}static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo){	unsigned char *data = wacom->data;	int x, y, id, rw;	if (data[0] != 2) {		dbg("wacom_graphire_irq: received unknown report #%d", data[0]);		return 0;	}	id = STYLUS_DEVICE_ID;	if (data[1] & 0x80) { /* in prox */		switch ((data[1] >> 5) & 3) {			case 0:	/* Pen */				wacom->tool[0] = BTN_TOOL_PEN;				break;			case 1: /* Rubber */				wacom->tool[0] = BTN_TOOL_RUBBER;				id = ERASER_DEVICE_ID;				break;			case 2: /* Mouse with wheel */				wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);				if (wacom->features->type == WACOM_G4 ||						wacom->features->type == WACOM_MO) {					rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);					wacom_report_rel(wcombo, REL_WHEEL, -rw);				} else					wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]);				/* fall through */			case 3: /* Mouse without wheel */				wacom->tool[0] = BTN_TOOL_MOUSE;				id = CURSOR_DEVICE_ID;				wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);				wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);				if (wacom->features->type == WACOM_G4 ||						wacom->features->type == WACOM_MO)					wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f);				else					wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);				break;		}		x = wacom_le16_to_cpu(&data[2]);		y = wacom_le16_to_cpu(&data[4]);		wacom_report_abs(wcombo, ABS_X, x);		wacom_report_abs(wcombo, ABS_Y, y);		if (wacom->tool[0] != BTN_TOOL_MOUSE) {			wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8));			wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);			wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);			wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);		}		wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */		wacom_report_key(wcombo, wacom->tool[0], 1);	} else if (!(data[1] & 0x90)) {		wacom_report_abs(wcombo, ABS_X, 0);		wacom_report_abs(wcombo, ABS_Y, 0);		if (wacom->tool[0] == BTN_TOOL_MOUSE) {			wacom_report_key(wcombo, BTN_LEFT, 0);			wacom_report_key(wcombo, BTN_RIGHT, 0);			wacom_report_abs(wcombo, ABS_DISTANCE, 0);		} else {			wacom_report_abs(wcombo, ABS_PRESSURE, 0);			wacom_report_key(wcombo, BTN_TOUCH, 0);			wacom_report_key(wcombo, BTN_STYLUS, 0);			wacom_report_key(wcombo, BTN_STYLUS2, 0);		}		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */		wacom_report_key(wcombo, wacom->tool[0], 0);	}	/* send pad data */	switch (wacom->features->type) {	    case WACOM_G4:		if (data[7] & 0xf8) {			wacom_input_sync(wcombo); /* sync last event */			wacom->id[1] = 1;			wacom->serial[1] = (data[7] & 0xf8);			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));			wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);			wacom_report_rel(wcombo, REL_WHEEL, rw);			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);			wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);		} else if (wacom->id[1]) {			wacom_input_sync(wcombo); /* sync last event */			wacom->id[1] = 0;			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));			wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);			wacom_report_abs(wcombo, ABS_MISC, 0);			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);		}		break;	    case WACOM_MO:		if ((data[7] & 0xf8) || (data[8] & 0x80)) {			wacom_input_sync(wcombo); /* sync last event */			wacom->id[1] = 1;			wacom->serial[1] = (data[7] & 0xf8);			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));			wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));			wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));			wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);			wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);		} else if (wacom->id[1]) {			wacom_input_sync(wcombo); /* sync last event */			wacom->id[1] = 0;			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));			wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));			wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));			wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);			wacom_report_abs(wcombo, ABS_MISC, 0);			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);		}		break;	}	return 1;}static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo){	unsigned char *data = wacom->data;	int idx;	/* tool number */	idx = data[1] & 0x01;	/* Enter report */	if ((data[1] & 0xfc) == 0xc0) {		/* serial number of the tool */		wacom->serial[idx] = ((data[3] & 0x0f) << 28) +			(data[4] << 20) + (data[5] << 12) +			(data[6] << 4) + (data[7] >> 4);		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);		switch (wacom->id[idx]) {			case 0x812: /* Inking pen */			case 0x801: /* Intuos3 Inking pen */			case 0x012:				wacom->tool[idx] = BTN_TOOL_PENCIL;				break;			case 0x822: /* Pen */			case 0x842:			case 0x852:			case 0x823: /* Intuos3 Grip Pen */			case 0x813: /* Intuos3 Classic Pen */			case 0x885: /* Intuos3 Marker Pen */			case 0x022:				wacom->tool[idx] = BTN_TOOL_PEN;				break;			case 0x832: /* Stroke pen */			case 0x032:				wacom->tool[idx] = BTN_TOOL_BRUSH;				break;			case 0x007: /* Mouse 4D and 2D */		        case 0x09c:			case 0x094:			case 0x017: /* Intuos3 2D Mouse */				wacom->tool[idx] = BTN_TOOL_MOUSE;				break;			case 0x096: /* Lens cursor */			case 0x097: /* Intuos3 Lens cursor */				wacom->tool[idx] = BTN_TOOL_LENS;				break;			case 0x82a: /* Eraser */			case 0x85a:		        case 0x91a:			case 0xd1a:			case 0x0fa:			case 0x82b: /* Intuos3 Grip Pen Eraser */			case 0x81b: /* Intuos3 Classic Pen Eraser */			case 0x91b: /* Intuos3 Airbrush Eraser */				wacom->tool[idx] = BTN_TOOL_RUBBER;				break;			case 0xd12:			case 0x912:			case 0x112:			case 0x913: /* Intuos3 Airbrush */				wacom->tool[idx] = BTN_TOOL_AIRBRUSH;				break;			default: /* Unknown tool */				wacom->tool[idx] = BTN_TOOL_PEN;		}		return 1;	}	/* Exit report */	if ((data[1] & 0xfe) == 0x80) {		wacom_report_abs(wcombo, ABS_X, 0);		wacom_report_abs(wcombo, ABS_Y, 0);		wacom_report_abs(wcombo, ABS_DISTANCE, 0);		if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?