| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 1 | /* | 
| Dmitry Torokhov | 4104d13 | 2007-05-07 16:16:29 -0400 | [diff] [blame] | 2 |  * drivers/input/tablet/wacom_wac.c | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 3 |  * | 
 | 4 |  *  USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code | 
 | 5 |  * | 
 | 6 |  */ | 
 | 7 |  | 
 | 8 | /* | 
 | 9 |  * This program is free software; you can redistribute it and/or modify | 
 | 10 |  * it under the terms of the GNU General Public License as published by | 
 | 11 |  * the Free Software Foundation; either version 2 of the License, or | 
 | 12 |  * (at your option) any later version. | 
 | 13 |  */ | 
 | 14 | #include "wacom.h" | 
 | 15 | #include "wacom_wac.h" | 
 | 16 |  | 
 | 17 | static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) | 
 | 18 | { | 
 | 19 | 	unsigned char *data = wacom->data; | 
 | 20 |  | 
 | 21 | 	switch (data[0]) { | 
 | 22 | 		case 1: | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 23 | 			if (data[5] & 0x80) { | 
 | 24 | 				wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 
 | 25 | 				wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID; | 
 | 26 | 				wacom_report_key(wcombo, wacom->tool[0], 1); | 
 | 27 | 				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | 
 | 28 | 				wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | 
 | 29 | 				wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | 
 | 30 | 				wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); | 
 | 31 | 				wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127)); | 
 | 32 | 				wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); | 
 | 33 | 			} else { | 
 | 34 | 				wacom_report_key(wcombo, wacom->tool[0], 0); | 
 | 35 | 				wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */ | 
 | 36 | 				wacom_report_abs(wcombo, ABS_PRESSURE, -1); | 
 | 37 | 				wacom_report_key(wcombo, BTN_TOUCH, 0); | 
 | 38 | 			} | 
 | 39 | 			break; | 
 | 40 | 		case 2: | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 41 | 			wacom_report_key(wcombo, BTN_TOOL_PEN, 1); | 
 | 42 | 			wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ | 
 | 43 | 			wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | 
 | 44 | 			wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | 
 | 45 | 			wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); | 
 | 46 | 			wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); | 
 | 47 | 			wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); | 
 | 48 | 			break; | 
 | 49 | 		default: | 
 | 50 | 			printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); | 
 | 51 | 			return 0; | 
 | 52 |         } | 
 | 53 | 	return 1; | 
 | 54 | } | 
 | 55 |  | 
 | 56 | static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) | 
 | 57 | { | 
 | 58 | 	unsigned char *data = wacom->data; | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 59 | 	int prox, pressure; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 60 |  | 
 | 61 | 	if (data[0] != 2) { | 
 | 62 | 		dbg("wacom_pl_irq: received unknown report #%d", data[0]); | 
 | 63 | 		return 0; | 
 | 64 | 	} | 
 | 65 |  | 
 | 66 | 	prox = data[1] & 0x40; | 
 | 67 |  | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 68 | 	wacom->id[0] = ERASER_DEVICE_ID; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 69 | 	if (prox) { | 
 | 70 |  | 
 | 71 | 		pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | 
 | 72 | 		if (wacom->features->pressure_max > 255) | 
 | 73 | 			pressure = (pressure << 1) | ((data[4] >> 6) & 1); | 
 | 74 | 		pressure += (wacom->features->pressure_max + 1) / 2; | 
 | 75 |  | 
 | 76 | 		/* | 
 | 77 | 		 * if going from out of proximity into proximity select between the eraser | 
 | 78 | 		 * and the pen based on the state of the stylus2 button, choose eraser if | 
 | 79 | 		 * pressed else choose pen. if not a proximity change from out to in, send | 
 | 80 | 		 * an out of proximity for previous tool then a in for new tool. | 
 | 81 | 		 */ | 
 | 82 | 		if (!wacom->tool[0]) { | 
 | 83 | 			/* Eraser bit set for DTF */ | 
 | 84 | 			if (data[1] & 0x10) | 
 | 85 | 				wacom->tool[1] = BTN_TOOL_RUBBER; | 
 | 86 | 			else | 
 | 87 | 				/* Going into proximity select tool */ | 
 | 88 | 				wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 
 | 89 | 		} else { | 
 | 90 | 			/* was entered with stylus2 pressed */ | 
 | 91 | 			if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) { | 
 | 92 | 				/* report out proximity for previous tool */ | 
 | 93 | 				wacom_report_key(wcombo, wacom->tool[1], 0); | 
 | 94 | 				wacom_input_sync(wcombo); | 
 | 95 | 				wacom->tool[1] = BTN_TOOL_PEN; | 
 | 96 | 				return 0; | 
 | 97 | 			} | 
 | 98 | 		} | 
 | 99 | 		if (wacom->tool[1] != BTN_TOOL_RUBBER) { | 
 | 100 | 			/* Unknown tool selected default to pen tool */ | 
 | 101 | 			wacom->tool[1] = BTN_TOOL_PEN; | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 102 | 			wacom->id[0] = STYLUS_DEVICE_ID; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 103 | 		} | 
 | 104 | 		wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */ | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 105 | 		wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 106 | 		wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); | 
 | 107 | 		wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); | 
 | 108 | 		wacom_report_abs(wcombo, ABS_PRESSURE, pressure); | 
 | 109 |  | 
 | 110 | 		wacom_report_key(wcombo, BTN_TOUCH, data[4] & 0x08); | 
 | 111 | 		wacom_report_key(wcombo, BTN_STYLUS, data[4] & 0x10); | 
 | 112 | 		/* Only allow the stylus2 button to be reported for the pen tool. */ | 
 | 113 | 		wacom_report_key(wcombo, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); | 
 | 114 | 	} else { | 
 | 115 | 		/* report proximity-out of a (valid) tool */ | 
 | 116 | 		if (wacom->tool[1] != BTN_TOOL_RUBBER) { | 
 | 117 | 			/* Unknown tool selected default to pen tool */ | 
 | 118 | 			wacom->tool[1] = BTN_TOOL_PEN; | 
 | 119 | 		} | 
 | 120 | 		wacom_report_key(wcombo, wacom->tool[1], prox); | 
 | 121 | 	} | 
 | 122 |  | 
 | 123 | 	wacom->tool[0] = prox; /* Save proximity state */ | 
 | 124 | 	return 1; | 
 | 125 | } | 
 | 126 |  | 
 | 127 | static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) | 
 | 128 | { | 
 | 129 | 	unsigned char *data = wacom->data; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 130 |  | 
 | 131 | 	if (data[0] != 2) { | 
 | 132 | 		printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); | 
 | 133 | 		return 0; | 
 | 134 | 	} | 
 | 135 |  | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 136 | 	if (data[1] & 0x04) { | 
 | 137 | 		wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20); | 
 | 138 | 		wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08); | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 139 | 		wacom->id[0] = ERASER_DEVICE_ID; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 140 | 	} else { | 
 | 141 | 		wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20); | 
 | 142 | 		wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 143 | 		wacom->id[0] = STYLUS_DEVICE_ID; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 144 | 	} | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 145 | 	wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 146 | 	wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | 
 | 147 | 	wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | 
 | 148 | 	wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | 
 | 149 | 	wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | 
 | 150 | 	wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); | 
 | 151 | 	return 1; | 
 | 152 | } | 
 | 153 |  | 
 | 154 | static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | 
 | 155 | { | 
 | 156 | 	unsigned char *data = wacom->data; | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 157 | 	int x, y, rw; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 158 |  | 
 | 159 | 	if (data[0] != 2) { | 
 | 160 | 		dbg("wacom_graphire_irq: received unknown report #%d", data[0]); | 
 | 161 | 		return 0; | 
 | 162 | 	} | 
 | 163 |  | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 164 | 	if (data[1] & 0x80) { | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 165 | 		/* in prox and not a pad data */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 166 |  | 
 | 167 | 		switch ((data[1] >> 5) & 3) { | 
 | 168 |  | 
 | 169 | 			case 0:	/* Pen */ | 
 | 170 | 				wacom->tool[0] = BTN_TOOL_PEN; | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 171 | 				wacom->id[0] = STYLUS_DEVICE_ID; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 172 | 				break; | 
 | 173 |  | 
 | 174 | 			case 1: /* Rubber */ | 
 | 175 | 				wacom->tool[0] = BTN_TOOL_RUBBER; | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 176 | 				wacom->id[0] = ERASER_DEVICE_ID; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 177 | 				break; | 
 | 178 |  | 
 | 179 | 			case 2: /* Mouse with wheel */ | 
 | 180 | 				wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 181 | 				if (wacom->features->type == WACOM_G4 || | 
 | 182 | 						wacom->features->type == WACOM_MO) { | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 183 | 					rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); | 
 | 184 | 					wacom_report_rel(wcombo, REL_WHEEL, -rw); | 
 | 185 | 				} else | 
 | 186 | 					wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]); | 
 | 187 | 				/* fall through */ | 
 | 188 |  | 
 | 189 | 			case 3: /* Mouse without wheel */ | 
 | 190 | 				wacom->tool[0] = BTN_TOOL_MOUSE; | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 191 | 				wacom->id[0] = CURSOR_DEVICE_ID; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 192 | 				wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); | 
 | 193 | 				wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 194 | 				if (wacom->features->type == WACOM_G4 || | 
 | 195 | 						wacom->features->type == WACOM_MO) | 
| Ping Cheng | 8d32e3a | 2006-09-26 13:34:47 -0700 | [diff] [blame] | 196 | 					wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 197 | 				else | 
| Ping Cheng | 8d32e3a | 2006-09-26 13:34:47 -0700 | [diff] [blame] | 198 | 					wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 199 | 				break; | 
 | 200 | 		} | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 201 | 		x = wacom_le16_to_cpu(&data[2]); | 
 | 202 | 		y = wacom_le16_to_cpu(&data[4]); | 
 | 203 | 		wacom_report_abs(wcombo, ABS_X, x); | 
 | 204 | 		wacom_report_abs(wcombo, ABS_Y, y); | 
 | 205 | 		if (wacom->tool[0] != BTN_TOOL_MOUSE) { | 
 | 206 | 			wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); | 
 | 207 | 			wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); | 
 | 208 | 			wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | 
 | 209 | 			wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); | 
 | 210 | 		} | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 211 | 		wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | 
| Ping Cheng | 071e0a2 | 2006-12-05 17:09:51 -0800 | [diff] [blame] | 212 | 		wacom_report_key(wcombo, wacom->tool[0], 1); | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 213 | 	} else if (wacom->id[0]) { | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 214 | 		wacom_report_abs(wcombo, ABS_X, 0); | 
 | 215 | 		wacom_report_abs(wcombo, ABS_Y, 0); | 
 | 216 | 		if (wacom->tool[0] == BTN_TOOL_MOUSE) { | 
 | 217 | 			wacom_report_key(wcombo, BTN_LEFT, 0); | 
 | 218 | 			wacom_report_key(wcombo, BTN_RIGHT, 0); | 
 | 219 | 			wacom_report_abs(wcombo, ABS_DISTANCE, 0); | 
 | 220 | 		} else { | 
 | 221 | 			wacom_report_abs(wcombo, ABS_PRESSURE, 0); | 
 | 222 | 			wacom_report_key(wcombo, BTN_TOUCH, 0); | 
 | 223 | 			wacom_report_key(wcombo, BTN_STYLUS, 0); | 
 | 224 | 			wacom_report_key(wcombo, BTN_STYLUS2, 0); | 
 | 225 | 		} | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 226 | 		wacom->id[0] = 0; | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 227 | 		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | 
| Ping Cheng | 071e0a2 | 2006-12-05 17:09:51 -0800 | [diff] [blame] | 228 | 		wacom_report_key(wcombo, wacom->tool[0], 0); | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 229 | 	} | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 230 |  | 
 | 231 | 	/* send pad data */ | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 232 | 	switch (wacom->features->type) { | 
 | 233 | 	    case WACOM_G4: | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 234 | 		if (data[7] & 0xf8) { | 
 | 235 | 			wacom_input_sync(wcombo); /* sync last event */ | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 236 | 			wacom->id[1] = PAD_DEVICE_ID; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 237 | 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | 
 | 238 | 			wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | 
 | 239 | 			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); | 
 | 240 | 			wacom_report_rel(wcombo, REL_WHEEL, rw); | 
 | 241 | 			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 242 | 			wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 243 | 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 
 | 244 | 		} else if (wacom->id[1]) { | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 245 | 			wacom_input_sync(wcombo); /* sync last event */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 246 | 			wacom->id[1] = 0; | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 247 | 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | 
 | 248 | 			wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 249 | 			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 250 | 			wacom_report_abs(wcombo, ABS_MISC, 0); | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 251 | 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 
 | 252 | 		} | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 253 | 		break; | 
 | 254 | 	    case WACOM_MO: | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 255 | 		if ((data[7] & 0xf8) || (data[8] & 0xff)) { | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 256 | 			wacom_input_sync(wcombo); /* sync last event */ | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 257 | 			wacom->id[1] = PAD_DEVICE_ID; | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 258 | 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | 
 | 259 | 			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | 
 | 260 | 			wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); | 
 | 261 | 			wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); | 
 | 262 | 			wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); | 
 | 263 | 			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | 
| Ping Cheng | e34b9d2 | 2008-05-05 11:36:41 -0400 | [diff] [blame] | 264 | 			wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 265 | 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 
 | 266 | 		} else if (wacom->id[1]) { | 
 | 267 | 			wacom_input_sync(wcombo); /* sync last event */ | 
 | 268 | 			wacom->id[1] = 0; | 
 | 269 | 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | 
 | 270 | 			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | 
 | 271 | 			wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); | 
 | 272 | 			wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); | 
 | 273 | 			wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); | 
 | 274 | 			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | 
 | 275 | 			wacom_report_abs(wcombo, ABS_MISC, 0); | 
 | 276 | 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 
 | 277 | 		} | 
 | 278 | 		break; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 279 | 	} | 
 | 280 | 	return 1; | 
 | 281 | } | 
 | 282 |  | 
 | 283 | static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | 
 | 284 | { | 
 | 285 | 	unsigned char *data = wacom->data; | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 286 | 	int idx = 0; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 287 |  | 
 | 288 | 	/* tool number */ | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 289 | 	if (wacom->features->type == INTUOS) | 
 | 290 | 		idx = data[1] & 0x01; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 291 |  | 
 | 292 | 	/* Enter report */ | 
 | 293 | 	if ((data[1] & 0xfc) == 0xc0) { | 
 | 294 | 		/* serial number of the tool */ | 
 | 295 | 		wacom->serial[idx] = ((data[3] & 0x0f) << 28) + | 
 | 296 | 			(data[4] << 20) + (data[5] << 12) + | 
 | 297 | 			(data[6] << 4) + (data[7] >> 4); | 
 | 298 |  | 
 | 299 | 		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4); | 
 | 300 | 		switch (wacom->id[idx]) { | 
 | 301 | 			case 0x812: /* Inking pen */ | 
 | 302 | 			case 0x801: /* Intuos3 Inking pen */ | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 303 | 			case 0x20802: /* Intuos4 Classic Pen */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 304 | 			case 0x012: | 
 | 305 | 				wacom->tool[idx] = BTN_TOOL_PENCIL; | 
 | 306 | 				break; | 
 | 307 | 			case 0x822: /* Pen */ | 
 | 308 | 			case 0x842: | 
 | 309 | 			case 0x852: | 
 | 310 | 			case 0x823: /* Intuos3 Grip Pen */ | 
 | 311 | 			case 0x813: /* Intuos3 Classic Pen */ | 
 | 312 | 			case 0x885: /* Intuos3 Marker Pen */ | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 313 | 			case 0x802: /* Intuos4 Grip Pen Eraser */ | 
 | 314 | 			case 0x804: /* Intuos4 Marker Pen */ | 
 | 315 | 			case 0x40802: /* Intuos4 Classic Pen */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 316 | 			case 0x022: | 
 | 317 | 				wacom->tool[idx] = BTN_TOOL_PEN; | 
 | 318 | 				break; | 
 | 319 | 			case 0x832: /* Stroke pen */ | 
 | 320 | 			case 0x032: | 
 | 321 | 				wacom->tool[idx] = BTN_TOOL_BRUSH; | 
 | 322 | 				break; | 
 | 323 | 			case 0x007: /* Mouse 4D and 2D */ | 
 | 324 | 		        case 0x09c: | 
 | 325 | 			case 0x094: | 
 | 326 | 			case 0x017: /* Intuos3 2D Mouse */ | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 327 | 			case 0x806: /* Intuos4 Mouse */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 328 | 				wacom->tool[idx] = BTN_TOOL_MOUSE; | 
 | 329 | 				break; | 
 | 330 | 			case 0x096: /* Lens cursor */ | 
 | 331 | 			case 0x097: /* Intuos3 Lens cursor */ | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 332 | 			case 0x006: /* Intuos4 Lens cursor */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 333 | 				wacom->tool[idx] = BTN_TOOL_LENS; | 
 | 334 | 				break; | 
 | 335 | 			case 0x82a: /* Eraser */ | 
 | 336 | 			case 0x85a: | 
 | 337 | 		        case 0x91a: | 
 | 338 | 			case 0xd1a: | 
 | 339 | 			case 0x0fa: | 
 | 340 | 			case 0x82b: /* Intuos3 Grip Pen Eraser */ | 
 | 341 | 			case 0x81b: /* Intuos3 Classic Pen Eraser */ | 
 | 342 | 			case 0x91b: /* Intuos3 Airbrush Eraser */ | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 343 | 			case 0x80c: /* Intuos4 Marker Pen Eraser */ | 
 | 344 | 			case 0x80a: /* Intuos4 Grip Pen Eraser */ | 
 | 345 | 			case 0x4080a: /* Intuos4 Classic Pen Eraser */ | 
 | 346 | 			case 0x90a: /* Intuos4 Airbrush Eraser */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 347 | 				wacom->tool[idx] = BTN_TOOL_RUBBER; | 
 | 348 | 				break; | 
 | 349 | 			case 0xd12: | 
 | 350 | 			case 0x912: | 
 | 351 | 			case 0x112: | 
 | 352 | 			case 0x913: /* Intuos3 Airbrush */ | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 353 | 			case 0x902: /* Intuos4 Airbrush */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 354 | 				wacom->tool[idx] = BTN_TOOL_AIRBRUSH; | 
 | 355 | 				break; | 
 | 356 | 			default: /* Unknown tool */ | 
 | 357 | 				wacom->tool[idx] = BTN_TOOL_PEN; | 
 | 358 | 		} | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 359 | 		return 1; | 
 | 360 | 	} | 
 | 361 |  | 
 | 362 | 	/* Exit report */ | 
 | 363 | 	if ((data[1] & 0xfe) == 0x80) { | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 364 | 		/* | 
 | 365 | 		 * Reset all states otherwise we lose the initial states | 
 | 366 | 		 * when in-prox next time | 
 | 367 | 		 */ | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 368 | 		wacom_report_abs(wcombo, ABS_X, 0); | 
 | 369 | 		wacom_report_abs(wcombo, ABS_Y, 0); | 
 | 370 | 		wacom_report_abs(wcombo, ABS_DISTANCE, 0); | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 371 | 		wacom_report_abs(wcombo, ABS_TILT_X, 0); | 
 | 372 | 		wacom_report_abs(wcombo, ABS_TILT_Y, 0); | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 373 | 		if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { | 
 | 374 | 			wacom_report_key(wcombo, BTN_LEFT, 0); | 
 | 375 | 			wacom_report_key(wcombo, BTN_MIDDLE, 0); | 
 | 376 | 			wacom_report_key(wcombo, BTN_RIGHT, 0); | 
 | 377 | 			wacom_report_key(wcombo, BTN_SIDE, 0); | 
 | 378 | 			wacom_report_key(wcombo, BTN_EXTRA, 0); | 
 | 379 | 			wacom_report_abs(wcombo, ABS_THROTTLE, 0); | 
 | 380 | 			wacom_report_abs(wcombo, ABS_RZ, 0); | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 381 | 		} else { | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 382 | 			wacom_report_abs(wcombo, ABS_PRESSURE, 0); | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 383 | 			wacom_report_key(wcombo, BTN_STYLUS, 0); | 
 | 384 | 			wacom_report_key(wcombo, BTN_STYLUS2, 0); | 
 | 385 | 			wacom_report_key(wcombo, BTN_TOUCH, 0); | 
 | 386 | 			wacom_report_abs(wcombo, ABS_WHEEL, 0); | 
| Ping Cheng | 8d32e3a | 2006-09-26 13:34:47 -0700 | [diff] [blame] | 387 | 		} | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 388 | 		wacom_report_key(wcombo, wacom->tool[idx], 0); | 
 | 389 | 		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | 
 | 390 | 		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 391 | 		wacom->id[idx] = 0; | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 392 | 		return 2; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 393 | 	} | 
 | 394 | 	return 0; | 
 | 395 | } | 
 | 396 |  | 
 | 397 | static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) | 
 | 398 | { | 
 | 399 | 	unsigned char *data = wacom->data; | 
 | 400 | 	unsigned int t; | 
 | 401 |  | 
 | 402 | 	/* general pen packet */ | 
 | 403 | 	if ((data[1] & 0xb8) == 0xa0) { | 
 | 404 | 		t = (data[6] << 2) | ((data[7] >> 6) & 3); | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 405 | 		if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) | 
 | 406 | 			t = (t << 1) | (data[1] & 1); | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 407 | 		wacom_report_abs(wcombo, ABS_PRESSURE, t); | 
 | 408 | 		wacom_report_abs(wcombo, ABS_TILT_X, | 
 | 409 | 				((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 
 | 410 | 		wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); | 
 | 411 | 		wacom_report_key(wcombo, BTN_STYLUS, data[1] & 2); | 
 | 412 | 		wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 4); | 
 | 413 | 		wacom_report_key(wcombo, BTN_TOUCH, t > 10); | 
 | 414 | 	} | 
 | 415 |  | 
 | 416 | 	/* airbrush second packet */ | 
 | 417 | 	if ((data[1] & 0xbc) == 0xb4) { | 
 | 418 | 		wacom_report_abs(wcombo, ABS_WHEEL, | 
 | 419 | 				(data[6] << 2) | ((data[7] >> 6) & 3)); | 
 | 420 | 		wacom_report_abs(wcombo, ABS_TILT_X, | 
 | 421 | 				((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 
 | 422 | 		wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); | 
 | 423 | 	} | 
 | 424 | 	return; | 
 | 425 | } | 
 | 426 |  | 
 | 427 | static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | 
 | 428 | { | 
 | 429 | 	unsigned char *data = wacom->data; | 
 | 430 | 	unsigned int t; | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 431 | 	int idx = 0, result; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 432 |  | 
 | 433 | 	if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { | 
 | 434 | 		dbg("wacom_intuos_irq: received unknown report #%d", data[0]); | 
 | 435 |                 return 0; | 
 | 436 | 	} | 
 | 437 |  | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 438 | 	/* tool number */ | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 439 | 	if (wacom->features->type == INTUOS) | 
 | 440 | 		idx = data[1] & 0x01; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 441 |  | 
 | 442 | 	/* pad packets. Works as a second tool and is always in prox */ | 
 | 443 | 	if (data[0] == 12) { | 
 | 444 | 		/* initiate the pad as a device */ | 
 | 445 | 		if (wacom->tool[1] != BTN_TOOL_FINGER) | 
 | 446 | 			wacom->tool[1] = BTN_TOOL_FINGER; | 
 | 447 |  | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 448 | 		if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) { | 
 | 449 | 			wacom_report_key(wcombo, BTN_0, (data[2] & 0x01)); | 
 | 450 | 			wacom_report_key(wcombo, BTN_1, (data[3] & 0x01)); | 
 | 451 | 			wacom_report_key(wcombo, BTN_2, (data[3] & 0x02)); | 
 | 452 | 			wacom_report_key(wcombo, BTN_3, (data[3] & 0x04)); | 
 | 453 | 			wacom_report_key(wcombo, BTN_4, (data[3] & 0x08)); | 
 | 454 | 			wacom_report_key(wcombo, BTN_5, (data[3] & 0x10)); | 
 | 455 | 			wacom_report_key(wcombo, BTN_6, (data[3] & 0x20)); | 
 | 456 | 			if (data[1] & 0x80) { | 
 | 457 | 				wacom_report_abs(wcombo, ABS_WHEEL, (data[1] & 0x7f)); | 
| Ping Cheng | a862952 | 2009-06-02 16:59:58 -0700 | [diff] [blame] | 458 | 			} else { | 
 | 459 | 				/* Out of proximity, clear wheel value. */ | 
 | 460 | 				wacom_report_abs(wcombo, ABS_WHEEL, 0); | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 461 | 			} | 
 | 462 | 			if (wacom->features->type != INTUOS4S) { | 
 | 463 | 				wacom_report_key(wcombo, BTN_7, (data[3] & 0x40)); | 
 | 464 | 				wacom_report_key(wcombo, BTN_8, (data[3] & 0x80)); | 
 | 465 | 			} | 
 | 466 | 			if (data[1] | (data[2] & 0x01) | data[3]) { | 
 | 467 | 				wacom_report_key(wcombo, wacom->tool[1], 1); | 
 | 468 | 				wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | 
 | 469 | 			} else { | 
 | 470 | 				wacom_report_key(wcombo, wacom->tool[1], 0); | 
 | 471 | 				wacom_report_abs(wcombo, ABS_MISC, 0); | 
 | 472 | 			} | 
 | 473 | 		} else { | 
 | 474 | 			wacom_report_key(wcombo, BTN_0, (data[5] & 0x01)); | 
 | 475 | 			wacom_report_key(wcombo, BTN_1, (data[5] & 0x02)); | 
 | 476 | 			wacom_report_key(wcombo, BTN_2, (data[5] & 0x04)); | 
 | 477 | 			wacom_report_key(wcombo, BTN_3, (data[5] & 0x08)); | 
 | 478 | 			wacom_report_key(wcombo, BTN_4, (data[6] & 0x01)); | 
 | 479 | 			wacom_report_key(wcombo, BTN_5, (data[6] & 0x02)); | 
 | 480 | 			wacom_report_key(wcombo, BTN_6, (data[6] & 0x04)); | 
 | 481 | 			wacom_report_key(wcombo, BTN_7, (data[6] & 0x08)); | 
 | 482 | 			wacom_report_key(wcombo, BTN_8, (data[5] & 0x10)); | 
 | 483 | 			wacom_report_key(wcombo, BTN_9, (data[6] & 0x10)); | 
 | 484 | 			wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); | 
 | 485 | 			wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 486 |  | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 487 | 			if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) | | 
 | 488 | 				data[2] | (data[3] & 0x1f) | data[4]) { | 
 | 489 | 				wacom_report_key(wcombo, wacom->tool[1], 1); | 
 | 490 | 				wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | 
 | 491 | 			} else { | 
 | 492 | 				wacom_report_key(wcombo, wacom->tool[1], 0); | 
 | 493 | 				wacom_report_abs(wcombo, ABS_MISC, 0); | 
 | 494 | 			} | 
 | 495 | 		} | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 496 | 		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff); | 
 | 497 |                 return 1; | 
 | 498 | 	} | 
 | 499 |  | 
 | 500 | 	/* process in/out prox events */ | 
 | 501 | 	result = wacom_intuos_inout(wacom, wcombo); | 
 | 502 | 	if (result) | 
 | 503 |                 return result-1; | 
 | 504 |  | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 505 | 	/* don't proceed if we don't know the ID */ | 
 | 506 | 	if (!wacom->id[idx]) | 
 | 507 | 		return 0; | 
 | 508 |  | 
 | 509 | 	/* Only large Intuos support Lense Cursor */ | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 510 | 	if ((wacom->tool[idx] == BTN_TOOL_LENS) | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 511 | 			&& ((wacom->features->type == INTUOS3) | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 512 | 			|| (wacom->features->type == INTUOS3S) | 
 | 513 | 			|| (wacom->features->type == INTUOS4) | 
 | 514 | 			|| (wacom->features->type == INTUOS4S))) | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 515 | 		return 0; | 
 | 516 |  | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 517 | 	/* Cintiq doesn't send data when RDY bit isn't set */ | 
 | 518 | 	if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) | 
 | 519 |                  return 0; | 
 | 520 |  | 
| Ping Cheng | 071e0a2 | 2006-12-05 17:09:51 -0800 | [diff] [blame] | 521 | 	if (wacom->features->type >= INTUOS3S) { | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 522 | 		wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); | 
 | 523 | 		wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); | 
 | 524 | 		wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); | 
 | 525 | 	} else { | 
 | 526 | 		wacom_report_abs(wcombo, ABS_X, wacom_be16_to_cpu(&data[2])); | 
 | 527 | 		wacom_report_abs(wcombo, ABS_Y, wacom_be16_to_cpu(&data[4])); | 
 | 528 | 		wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); | 
 | 529 | 	} | 
 | 530 |  | 
 | 531 | 	/* process general packets */ | 
 | 532 | 	wacom_intuos_general(wacom, wcombo); | 
 | 533 |  | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 534 | 	/* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */ | 
 | 535 | 	if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) { | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 536 |  | 
 | 537 | 		if (data[1] & 0x02) { | 
 | 538 | 			/* Rotation packet */ | 
| Ping Cheng | 071e0a2 | 2006-12-05 17:09:51 -0800 | [diff] [blame] | 539 | 			if (wacom->features->type >= INTUOS3S) { | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 540 | 				/* I3 marker pen rotation */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 541 | 				t = (data[6] << 3) | ((data[7] >> 5) & 7); | 
 | 542 | 				t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : | 
 | 543 | 					((t-1) / 2 + 450)) : (450 - t / 2) ; | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 544 | 				wacom_report_abs(wcombo, ABS_Z, t); | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 545 | 			} else { | 
 | 546 | 				/* 4D mouse rotation packet */ | 
 | 547 | 				t = (data[6] << 3) | ((data[7] >> 5) & 7); | 
 | 548 | 				wacom_report_abs(wcombo, ABS_RZ, (data[7] & 0x20) ? | 
 | 549 | 					((t - 1) / 2) : -t / 2); | 
 | 550 | 			} | 
 | 551 |  | 
| Ping Cheng | 8d32e3a | 2006-09-26 13:34:47 -0700 | [diff] [blame] | 552 | 		} else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3S) { | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 553 | 			/* 4D mouse packet */ | 
 | 554 | 			wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01); | 
 | 555 | 			wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); | 
 | 556 | 			wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04); | 
 | 557 |  | 
 | 558 | 			wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x20); | 
 | 559 | 			wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x10); | 
 | 560 | 			t = (data[6] << 2) | ((data[7] >> 6) & 3); | 
 | 561 | 			wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | 
 | 562 |  | 
 | 563 | 		} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 564 | 			/* I4 mouse */ | 
 | 565 | 			if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) { | 
 | 566 | 				wacom_report_key(wcombo, BTN_LEFT,   data[6] & 0x01); | 
 | 567 | 				wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02); | 
 | 568 | 				wacom_report_key(wcombo, BTN_RIGHT,  data[6] & 0x04); | 
 | 569 | 				wacom_report_rel(wcombo, REL_WHEEL, ((data[7] & 0x80) >> 7) | 
 | 570 | 						 - ((data[7] & 0x40) >> 6)); | 
 | 571 | 				wacom_report_key(wcombo, BTN_SIDE,   data[6] & 0x08); | 
 | 572 | 				wacom_report_key(wcombo, BTN_EXTRA,  data[6] & 0x10); | 
 | 573 |  | 
 | 574 | 				wacom_report_abs(wcombo, ABS_TILT_X, | 
 | 575 | 					((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 
 | 576 | 				wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); | 
 | 577 | 			} else { | 
 | 578 | 				/* 2D mouse packet */ | 
 | 579 | 				wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x04); | 
 | 580 | 				wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08); | 
 | 581 | 				wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x10); | 
 | 582 | 				wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01) | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 583 | 						 - ((data[8] & 0x02) >> 1)); | 
 | 584 |  | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 585 | 				/* I3 2D mouse side buttons */ | 
 | 586 | 				if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) { | 
 | 587 | 					wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x40); | 
 | 588 | 					wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x20); | 
 | 589 | 				} | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 590 | 			} | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 591 | 		} else if ((wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L || | 
 | 592 | 				wacom->features->type == INTUOS4L) && | 
 | 593 | 			   wacom->tool[idx] == BTN_TOOL_LENS) { | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 594 | 			/* Lens cursor packets */ | 
 | 595 | 			wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01); | 
 | 596 | 			wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); | 
 | 597 | 			wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04); | 
 | 598 | 			wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x10); | 
 | 599 | 			wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x08); | 
 | 600 | 		} | 
 | 601 | 	} | 
 | 602 |  | 
 | 603 | 	wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */ | 
 | 604 | 	wacom_report_key(wcombo, wacom->tool[idx], 1); | 
 | 605 | 	wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | 
 | 606 | 	return 1; | 
 | 607 | } | 
 | 608 |  | 
| Roel Kluin | 0de048a | 2008-12-20 05:19:43 -0500 | [diff] [blame] | 609 | static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 610 | { | 
 | 611 | 	char *data = wacom->data; | 
 | 612 | 	int prox = 0, pressure; | 
 | 613 | 	static int stylusInProx, touchInProx = 1, touchOut; | 
 | 614 | 	struct urb *urb = ((struct wacom_combo *)wcombo)->urb; | 
 | 615 |  | 
 | 616 | 	dbg("wacom_tpc_irq: received report #%d", data[0]); | 
 | 617 |  | 
 | 618 | 	if (urb->actual_length == 5 || data[0] == 6) { /* Touch data */ | 
 | 619 | 		if (urb->actual_length == 5) {  /* with touch */ | 
 | 620 | 			prox = data[0] & 0x03; | 
 | 621 | 		} else {  /* with capacity */ | 
 | 622 | 			prox = data[1] & 0x03; | 
 | 623 | 		} | 
 | 624 |  | 
 | 625 | 		if (!stylusInProx) { /* stylus not in prox */ | 
 | 626 | 			if (prox) { | 
 | 627 | 				if (touchInProx) { | 
 | 628 | 					wacom->tool[1] = BTN_TOOL_DOUBLETAP; | 
 | 629 | 					wacom->id[0] = TOUCH_DEVICE_ID; | 
 | 630 | 					if (urb->actual_length != 5) { | 
 | 631 | 						wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | 
 | 632 | 						wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | 
 | 633 | 						wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | 
 | 634 | 						wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); | 
 | 635 | 					} else { | 
 | 636 | 						wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | 
 | 637 | 						wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | 
 | 638 | 						wacom_report_key(wcombo, BTN_TOUCH, 1); | 
 | 639 | 					} | 
 | 640 | 					wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 
 | 641 | 					wacom_report_key(wcombo, wacom->tool[1], prox & 0x01); | 
 | 642 | 					touchOut = 1; | 
 | 643 | 					return 1; | 
 | 644 | 				} | 
 | 645 | 			} else { | 
 | 646 | 				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 
 | 647 | 				wacom_report_key(wcombo, wacom->tool[1], prox & 0x01); | 
 | 648 | 				wacom_report_key(wcombo, BTN_TOUCH, 0); | 
 | 649 | 				touchOut = 0; | 
 | 650 | 				touchInProx = 1; | 
 | 651 | 				return 1; | 
 | 652 | 			} | 
 | 653 | 		} else if (touchOut || !prox) { /* force touch out-prox */ | 
 | 654 | 			wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 655 | 			wacom_report_key(wcombo, wacom->tool[1], 0); | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 656 | 			wacom_report_key(wcombo, BTN_TOUCH, 0); | 
 | 657 | 			touchOut = 0; | 
 | 658 | 			touchInProx = 1; | 
 | 659 | 			return 1; | 
 | 660 | 		} | 
 | 661 | 	} else if (data[0] == 2) { /* Penabled */ | 
 | 662 | 		prox = data[1] & 0x20; | 
 | 663 |  | 
 | 664 | 		touchInProx = 0; | 
 | 665 |  | 
 | 666 | 		wacom->id[0] = ERASER_DEVICE_ID; | 
 | 667 |  | 
 | 668 | 		/* | 
 | 669 | 		 * if going from out of proximity into proximity select between the eraser | 
 | 670 | 		 * and the pen based on the state of the stylus2 button, choose eraser if | 
 | 671 | 		 * pressed else choose pen. if not a proximity change from out to in, send | 
 | 672 | 		 * an out of proximity for previous tool then a in for new tool. | 
 | 673 | 		 */ | 
 | 674 | 		if (prox) { /* in prox */ | 
 | 675 | 			if (!wacom->tool[0]) { | 
 | 676 | 				/* Going into proximity select tool */ | 
 | 677 | 				wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 
 | 678 | 				if (wacom->tool[1] == BTN_TOOL_PEN) | 
 | 679 | 					wacom->id[0] = STYLUS_DEVICE_ID; | 
 | 680 | 			} else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) { | 
 | 681 | 				/* | 
 | 682 | 				 * was entered with stylus2 pressed | 
 | 683 | 				 * report out proximity for previous tool | 
 | 684 | 				*/ | 
 | 685 | 				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 
 | 686 | 				wacom_report_key(wcombo, wacom->tool[1], 0); | 
 | 687 | 				wacom_input_sync(wcombo); | 
 | 688 |  | 
 | 689 | 				/* set new tool */ | 
 | 690 | 				wacom->tool[1] = BTN_TOOL_PEN; | 
 | 691 | 				wacom->id[0] = STYLUS_DEVICE_ID; | 
 | 692 | 				return 0; | 
 | 693 | 			} | 
 | 694 | 			if (wacom->tool[1] != BTN_TOOL_RUBBER) { | 
 | 695 | 				/* Unknown tool selected default to pen tool */ | 
 | 696 | 				wacom->tool[1] = BTN_TOOL_PEN; | 
 | 697 | 				wacom->id[0] = STYLUS_DEVICE_ID; | 
 | 698 | 			} | 
 | 699 | 			wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | 
 | 700 | 			wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); | 
 | 701 | 			wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | 
 | 702 | 			wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | 
 | 703 | 			pressure = ((data[7] & 0x01) << 8) | data[6]; | 
 | 704 | 			if (pressure < 0) | 
 | 705 | 				pressure = wacom->features->pressure_max + pressure + 1; | 
 | 706 | 			wacom_report_abs(wcombo, ABS_PRESSURE, pressure); | 
 | 707 | 			wacom_report_key(wcombo, BTN_TOUCH, pressure); | 
 | 708 | 		} else { | 
 | 709 | 			wacom_report_abs(wcombo, ABS_PRESSURE, 0); | 
 | 710 | 			wacom_report_key(wcombo, BTN_STYLUS, 0); | 
 | 711 | 			wacom_report_key(wcombo, BTN_STYLUS2, 0); | 
 | 712 | 			wacom_report_key(wcombo, BTN_TOUCH, 0); | 
 | 713 | 		} | 
 | 714 | 		wacom_report_key(wcombo, wacom->tool[1], prox); | 
 | 715 | 		wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 
 | 716 | 		stylusInProx = prox; | 
 | 717 | 		wacom->tool[0] = prox; | 
 | 718 | 		return 1; | 
 | 719 | 	} | 
 | 720 | 	return 0; | 
 | 721 | } | 
 | 722 |  | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 723 | int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | 
 | 724 | { | 
 | 725 | 	switch (wacom_wac->features->type) { | 
 | 726 | 		case PENPARTNER: | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 727 | 			return wacom_penpartner_irq(wacom_wac, wcombo); | 
 | 728 |  | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 729 | 		case PL: | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 730 | 			return wacom_pl_irq(wacom_wac, wcombo); | 
 | 731 |  | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 732 | 		case WACOM_G4: | 
 | 733 | 		case GRAPHIRE: | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 734 | 		case WACOM_MO: | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 735 | 			return wacom_graphire_irq(wacom_wac, wcombo); | 
 | 736 |  | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 737 | 		case PTU: | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 738 | 			return wacom_ptu_irq(wacom_wac, wcombo); | 
 | 739 |  | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 740 | 		case INTUOS: | 
| Ping Cheng | 8d32e3a | 2006-09-26 13:34:47 -0700 | [diff] [blame] | 741 | 		case INTUOS3S: | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 742 | 		case INTUOS3: | 
 | 743 | 		case INTUOS3L: | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 744 | 		case INTUOS4S: | 
 | 745 | 		case INTUOS4: | 
 | 746 | 		case INTUOS4L: | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 747 | 		case CINTIQ: | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 748 | 		case WACOM_BEE: | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 749 | 			return wacom_intuos_irq(wacom_wac, wcombo); | 
 | 750 |  | 
 | 751 | 		case TABLETPC: | 
 | 752 | 			return wacom_tpc_irq(wacom_wac, wcombo); | 
 | 753 |  | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 754 | 		default: | 
 | 755 | 			return 0; | 
 | 756 | 	} | 
 | 757 | 	return 0; | 
 | 758 | } | 
 | 759 |  | 
 | 760 | void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 
 | 761 | { | 
 | 762 | 	switch (wacom_wac->features->type) { | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 763 | 		case WACOM_MO: | 
 | 764 | 			input_dev_mo(input_dev, wacom_wac); | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 765 | 		case WACOM_G4: | 
 | 766 | 			input_dev_g4(input_dev, wacom_wac); | 
 | 767 | 			/* fall through */ | 
 | 768 | 		case GRAPHIRE: | 
 | 769 | 			input_dev_g(input_dev, wacom_wac); | 
 | 770 | 			break; | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 771 | 		case WACOM_BEE: | 
 | 772 | 			input_dev_bee(input_dev, wacom_wac); | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 773 | 		case INTUOS3: | 
 | 774 | 		case INTUOS3L: | 
 | 775 | 		case CINTIQ: | 
 | 776 | 			input_dev_i3(input_dev, wacom_wac); | 
 | 777 | 			/* fall through */ | 
| Ping Cheng | 8d32e3a | 2006-09-26 13:34:47 -0700 | [diff] [blame] | 778 | 		case INTUOS3S: | 
 | 779 | 			input_dev_i3s(input_dev, wacom_wac); | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 780 | 			/* fall through */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 781 | 		case INTUOS: | 
 | 782 | 			input_dev_i(input_dev, wacom_wac); | 
 | 783 | 			break; | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 784 | 		case INTUOS4: | 
 | 785 | 		case INTUOS4L: | 
 | 786 | 			input_dev_i4(input_dev, wacom_wac); | 
 | 787 | 			/* fall through */ | 
 | 788 | 		case INTUOS4S: | 
 | 789 | 			input_dev_i4s(input_dev, wacom_wac); | 
 | 790 | 			input_dev_i(input_dev, wacom_wac); | 
 | 791 | 			break; | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 792 | 		case PL: | 
 | 793 | 		case PTU: | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 794 | 		case TABLETPC: | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 795 | 			input_dev_pl(input_dev, wacom_wac); | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 796 | 			/* fall through */ | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 797 | 		case PENPARTNER: | 
 | 798 | 			input_dev_pt(input_dev, wacom_wac); | 
 | 799 | 			break; | 
 | 800 | 	} | 
 | 801 | 	return; | 
 | 802 | } | 
 | 803 |  | 
 | 804 | static struct wacom_features wacom_features[] = { | 
| Ping Cheng | 8d32e3a | 2006-09-26 13:34:47 -0700 | [diff] [blame] | 805 | 	{ "Wacom Penpartner",    7,   5040,  3780,  255,  0, PENPARTNER }, | 
 | 806 |         { "Wacom Graphire",      8,  10206,  7422,  511, 63, GRAPHIRE }, | 
 | 807 | 	{ "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 63, GRAPHIRE }, | 
 | 808 | 	{ "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 63, GRAPHIRE }, | 
 | 809 | 	{ "Wacom Graphire3",     8,  10208,  7424,  511, 63, GRAPHIRE }, | 
 | 810 | 	{ "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 63, GRAPHIRE }, | 
 | 811 | 	{ "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 63, WACOM_G4 }, | 
 | 812 | 	{ "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 63, WACOM_G4 }, | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 813 | 	{ "Wacom BambooFun 4x5", 9,  14760,  9225,  511, 63, WACOM_MO }, | 
 | 814 | 	{ "Wacom BambooFun 6x8", 9,  21648, 13530,  511, 63, WACOM_MO }, | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 815 | 	{ "Wacom Bamboo1 Medium",8,  16704, 12064,  511, 63, GRAPHIRE }, | 
| Ping Cheng | 071e0a2 | 2006-12-05 17:09:51 -0800 | [diff] [blame] | 816 | 	{ "Wacom Volito",        8,   5104,  3712,  511, 63, GRAPHIRE }, | 
 | 817 | 	{ "Wacom PenStation2",   8,   3250,  2320,  255, 63, GRAPHIRE }, | 
 | 818 | 	{ "Wacom Volito2 4x5",   8,   5104,  3712,  511, 63, GRAPHIRE }, | 
 | 819 | 	{ "Wacom Volito2 2x3",   8,   3248,  2320,  511, 63, GRAPHIRE }, | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 820 | 	{ "Wacom PenPartner2",   8,   3250,  2320,  511, 63, GRAPHIRE }, | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 821 | 	{ "Wacom Bamboo",        9,  14760,  9225,  511, 63, WACOM_MO }, | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 822 | 	{ "Wacom Bamboo1",       8,   5104,  3712,  511, 63, GRAPHIRE }, | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 823 | 	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 31, INTUOS }, | 
 | 824 | 	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 31, INTUOS }, | 
 | 825 | 	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 31, INTUOS }, | 
 | 826 | 	{ "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 31, INTUOS }, | 
 | 827 | 	{ "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 31, INTUOS }, | 
| Ping Cheng | 8d32e3a | 2006-09-26 13:34:47 -0700 | [diff] [blame] | 828 | 	{ "Wacom PL400",         8,   5408,  4056,  255,  0, PL }, | 
 | 829 | 	{ "Wacom PL500",         8,   6144,  4608,  255,  0, PL }, | 
 | 830 | 	{ "Wacom PL600",         8,   6126,  4604,  255,  0, PL }, | 
 | 831 | 	{ "Wacom PL600SX",       8,   6260,  5016,  255,  0, PL }, | 
 | 832 | 	{ "Wacom PL550",         8,   6144,  4608,  511,  0, PL }, | 
 | 833 | 	{ "Wacom PL800",         8,   7220,  5780,  511,  0, PL }, | 
 | 834 | 	{ "Wacom PL700",         8,   6758,  5406,  511,  0, PL }, | 
 | 835 | 	{ "Wacom PL510",         8,   6282,  4762,  511,  0, PL }, | 
 | 836 | 	{ "Wacom DTU710",        8,  34080, 27660,  511,  0, PL }, | 
 | 837 | 	{ "Wacom DTF521",        8,   6282,  4762,  511,  0, PL }, | 
 | 838 | 	{ "Wacom DTF720",        8,   6858,  5506,  511,  0, PL }, | 
 | 839 | 	{ "Wacom Cintiq Partner",8,  20480, 15360,  511,  0, PTU }, | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 840 | 	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 31, INTUOS }, | 
 | 841 | 	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS }, | 
 | 842 | 	{ "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 31, INTUOS }, | 
 | 843 | 	{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS }, | 
 | 844 | 	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS }, | 
| Ping Cheng | 8d32e3a | 2006-09-26 13:34:47 -0700 | [diff] [blame] | 845 | 	{ "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 63, INTUOS3S }, | 
 | 846 | 	{ "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 63, INTUOS3 }, | 
 | 847 | 	{ "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 63, INTUOS3 }, | 
 | 848 | 	{ "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L }, | 
 | 849 | 	{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L }, | 
 | 850 | 	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 }, | 
| Ping Cheng | 071e0a2 | 2006-12-05 17:09:51 -0800 | [diff] [blame] | 851 | 	{ "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 63, INTUOS3S }, | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 852 | 	{ "Wacom Intuos4 4x6",   10, 31496, 19685, 2047, 63, INTUOS4S }, | 
 | 853 | 	{ "Wacom Intuos4 6x9",   10, 44704, 27940, 2047, 63, INTUOS4 }, | 
 | 854 | 	{ "Wacom Intuos4 8x13",  10, 65024, 40640, 2047, 63, INTUOS4L }, | 
 | 855 | 	{ "Wacom Intuos4 12x19", 10, 97536, 60960, 2047, 63, INTUOS4L }, | 
| Ping Cheng | 8d32e3a | 2006-09-26 13:34:47 -0700 | [diff] [blame] | 856 | 	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ }, | 
| Ping Cheng | b345dc7 | 2008-04-24 23:34:05 -0400 | [diff] [blame] | 857 | 	{ "Wacom Cintiq 20WSX",  10, 86680, 54180, 1023, 63, WACOM_BEE }, | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 858 | 	{ "Wacom Cintiq 12WX",   10, 53020, 33440, 1023, 63, WACOM_BEE }, | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 859 | 	{ "Wacom DTU1931",        8, 37832, 30305,  511,  0, PL }, | 
 | 860 | 	{ "Wacom ISDv4 90",       8, 26202, 16325,  255,  0, TABLETPC }, | 
 | 861 | 	{ "Wacom ISDv4 93",       8, 26202, 16325,  255,  0, TABLETPC }, | 
 | 862 | 	{ "Wacom ISDv4 9A",       8, 26202, 16325,  255,  0, TABLETPC }, | 
| Ping Cheng | 80d4e8e | 2007-02-23 12:22:48 -0800 | [diff] [blame] | 863 | 	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS }, | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 864 | 	{ } | 
 | 865 | }; | 
 | 866 |  | 
 | 867 | static struct usb_device_id wacom_ids[] = { | 
 | 868 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) }, | 
 | 869 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) }, | 
 | 870 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) }, | 
 | 871 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) }, | 
 | 872 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) }, | 
 | 873 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) }, | 
 | 874 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) }, | 
 | 875 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) }, | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 876 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) }, | 
 | 877 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) }, | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 878 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x19) }, | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 879 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, | 
 | 880 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) }, | 
 | 881 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, | 
 | 882 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) }, | 
 | 883 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) }, | 
| Ping Cheng | 7ecfbfd | 2007-06-14 23:32:48 -0400 | [diff] [blame] | 884 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) }, | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 885 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x69) }, | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 886 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, | 
 | 887 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, | 
 | 888 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, | 
 | 889 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) }, | 
 | 890 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) }, | 
 | 891 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) }, | 
 | 892 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) }, | 
 | 893 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) }, | 
 | 894 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) }, | 
 | 895 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) }, | 
 | 896 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) }, | 
 | 897 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, | 
 | 898 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, | 
 | 899 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, | 
 | 900 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, | 
 | 901 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, | 
 | 902 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, | 
 | 903 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, | 
 | 904 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, | 
 | 905 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) }, | 
 | 906 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) }, | 
 | 907 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) }, | 
 | 908 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, | 
 | 909 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, | 
 | 910 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, | 
 | 911 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) }, | 
 | 912 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) }, | 
 | 913 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, | 
| Ping Cheng | 8d32e3a | 2006-09-26 13:34:47 -0700 | [diff] [blame] | 914 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) }, | 
| Ping Cheng | 6f660f1 | 2009-05-08 18:30:33 -0700 | [diff] [blame] | 915 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB8) }, | 
 | 916 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB9) }, | 
 | 917 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBA) }, | 
 | 918 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBB) }, | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 919 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, | 
| Ping Cheng | b345dc7 | 2008-04-24 23:34:05 -0400 | [diff] [blame] | 920 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) }, | 
| Ping Cheng | 0e1763f | 2008-03-13 16:46:46 -0400 | [diff] [blame] | 921 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) }, | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 922 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC7) }, | 
 | 923 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) }, | 
 | 924 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) }, | 
 | 925 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) }, | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 926 | 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, | 
 | 927 | 	{ } | 
 | 928 | }; | 
 | 929 |  | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 930 | const struct usb_device_id *get_device_table(void) | 
 | 931 | { | 
 | 932 |         const struct usb_device_id *id_table = wacom_ids; | 
 | 933 |  | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 934 |         return id_table; | 
 | 935 | } | 
 | 936 |  | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 937 | struct wacom_features * get_wacom_feature(const struct usb_device_id *id) | 
 | 938 | { | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 939 |         int index = id - wacom_ids; | 
 | 940 |         struct wacom_features *wf = &wacom_features[index]; | 
| Ping Cheng | 545f4e9 | 2008-11-24 11:44:27 -0500 | [diff] [blame] | 941 |  | 
| Ping Cheng | 3bea733 | 2006-07-13 18:01:36 -0700 | [diff] [blame] | 942 |         return wf; | 
 | 943 | } | 
 | 944 |  | 
 | 945 | MODULE_DEVICE_TABLE(usb, wacom_ids); |