diff options
Diffstat (limited to 'drivers/input/mouse/synaptics.c')
-rw-r--r-- | drivers/input/mouse/synaptics.c | 197 |
1 files changed, 142 insertions, 55 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index a6dcd18e9adf..8081a0a5d602 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -269,19 +269,49 @@ static int synaptics_query_hardware(struct psmouse *psmouse) | |||
269 | return 0; | 269 | return 0; |
270 | } | 270 | } |
271 | 271 | ||
272 | static int synaptics_set_absolute_mode(struct psmouse *psmouse) | 272 | static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) |
273 | { | ||
274 | static unsigned char param = 0xc8; | ||
275 | struct synaptics_data *priv = psmouse->private; | ||
276 | |||
277 | if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | ||
278 | return 0; | ||
279 | |||
280 | if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) | ||
281 | return -1; | ||
282 | |||
283 | if (ps2_command(&psmouse->ps2dev, ¶m, PSMOUSE_CMD_SETRATE)) | ||
284 | return -1; | ||
285 | |||
286 | /* Advanced gesture mode also sends multi finger data */ | ||
287 | priv->capabilities |= BIT(1); | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int synaptics_set_mode(struct psmouse *psmouse) | ||
273 | { | 293 | { |
274 | struct synaptics_data *priv = psmouse->private; | 294 | struct synaptics_data *priv = psmouse->private; |
275 | 295 | ||
276 | priv->mode = SYN_BIT_ABSOLUTE_MODE; | 296 | priv->mode = 0; |
277 | if (SYN_ID_MAJOR(priv->identity) >= 4) | 297 | if (priv->absolute_mode) |
298 | priv->mode |= SYN_BIT_ABSOLUTE_MODE; | ||
299 | if (priv->disable_gesture) | ||
278 | priv->mode |= SYN_BIT_DISABLE_GESTURE; | 300 | priv->mode |= SYN_BIT_DISABLE_GESTURE; |
301 | if (psmouse->rate >= 80) | ||
302 | priv->mode |= SYN_BIT_HIGH_RATE; | ||
279 | if (SYN_CAP_EXTENDED(priv->capabilities)) | 303 | if (SYN_CAP_EXTENDED(priv->capabilities)) |
280 | priv->mode |= SYN_BIT_W_MODE; | 304 | priv->mode |= SYN_BIT_W_MODE; |
281 | 305 | ||
282 | if (synaptics_mode_cmd(psmouse, priv->mode)) | 306 | if (synaptics_mode_cmd(psmouse, priv->mode)) |
283 | return -1; | 307 | return -1; |
284 | 308 | ||
309 | if (priv->absolute_mode && | ||
310 | synaptics_set_advanced_gesture_mode(psmouse)) { | ||
311 | psmouse_err(psmouse, "Advanced gesture mode init failed.\n"); | ||
312 | return -1; | ||
313 | } | ||
314 | |||
285 | return 0; | 315 | return 0; |
286 | } | 316 | } |
287 | 317 | ||
@@ -300,26 +330,6 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate) | |||
300 | synaptics_mode_cmd(psmouse, priv->mode); | 330 | synaptics_mode_cmd(psmouse, priv->mode); |
301 | } | 331 | } |
302 | 332 | ||
303 | static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) | ||
304 | { | ||
305 | static unsigned char param = 0xc8; | ||
306 | struct synaptics_data *priv = psmouse->private; | ||
307 | |||
308 | if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || | ||
309 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))) | ||
310 | return 0; | ||
311 | |||
312 | if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) | ||
313 | return -1; | ||
314 | if (ps2_command(&psmouse->ps2dev, ¶m, PSMOUSE_CMD_SETRATE)) | ||
315 | return -1; | ||
316 | |||
317 | /* Advanced gesture mode also sends multi finger data */ | ||
318 | priv->capabilities |= BIT(1); | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | /***************************************************************************** | 333 | /***************************************************************************** |
324 | * Synaptics pass-through PS/2 port support | 334 | * Synaptics pass-through PS/2 port support |
325 | ****************************************************************************/ | 335 | ****************************************************************************/ |
@@ -1143,8 +1153,24 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
1143 | { | 1153 | { |
1144 | int i; | 1154 | int i; |
1145 | 1155 | ||
1156 | /* Things that apply to both modes */ | ||
1146 | __set_bit(INPUT_PROP_POINTER, dev->propbit); | 1157 | __set_bit(INPUT_PROP_POINTER, dev->propbit); |
1158 | __set_bit(EV_KEY, dev->evbit); | ||
1159 | __set_bit(BTN_LEFT, dev->keybit); | ||
1160 | __set_bit(BTN_RIGHT, dev->keybit); | ||
1147 | 1161 | ||
1162 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) | ||
1163 | __set_bit(BTN_MIDDLE, dev->keybit); | ||
1164 | |||
1165 | if (!priv->absolute_mode) { | ||
1166 | /* Relative mode */ | ||
1167 | __set_bit(EV_REL, dev->evbit); | ||
1168 | __set_bit(REL_X, dev->relbit); | ||
1169 | __set_bit(REL_Y, dev->relbit); | ||
1170 | return; | ||
1171 | } | ||
1172 | |||
1173 | /* Absolute mode */ | ||
1148 | __set_bit(EV_ABS, dev->evbit); | 1174 | __set_bit(EV_ABS, dev->evbit); |
1149 | set_abs_position_params(dev, priv, ABS_X, ABS_Y); | 1175 | set_abs_position_params(dev, priv, ABS_X, ABS_Y); |
1150 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 1176 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
@@ -1170,20 +1196,14 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
1170 | if (SYN_CAP_PALMDETECT(priv->capabilities)) | 1196 | if (SYN_CAP_PALMDETECT(priv->capabilities)) |
1171 | input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); | 1197 | input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); |
1172 | 1198 | ||
1173 | __set_bit(EV_KEY, dev->evbit); | ||
1174 | __set_bit(BTN_TOUCH, dev->keybit); | 1199 | __set_bit(BTN_TOUCH, dev->keybit); |
1175 | __set_bit(BTN_TOOL_FINGER, dev->keybit); | 1200 | __set_bit(BTN_TOOL_FINGER, dev->keybit); |
1176 | __set_bit(BTN_LEFT, dev->keybit); | ||
1177 | __set_bit(BTN_RIGHT, dev->keybit); | ||
1178 | 1201 | ||
1179 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { | 1202 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { |
1180 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); | 1203 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); |
1181 | __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); | 1204 | __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); |
1182 | } | 1205 | } |
1183 | 1206 | ||
1184 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) | ||
1185 | __set_bit(BTN_MIDDLE, dev->keybit); | ||
1186 | |||
1187 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities) || | 1207 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities) || |
1188 | SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { | 1208 | SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { |
1189 | __set_bit(BTN_FORWARD, dev->keybit); | 1209 | __set_bit(BTN_FORWARD, dev->keybit); |
@@ -1205,10 +1225,58 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
1205 | } | 1225 | } |
1206 | } | 1226 | } |
1207 | 1227 | ||
1228 | static ssize_t synaptics_show_disable_gesture(struct psmouse *psmouse, | ||
1229 | void *data, char *buf) | ||
1230 | { | ||
1231 | struct synaptics_data *priv = psmouse->private; | ||
1232 | |||
1233 | return sprintf(buf, "%c\n", priv->disable_gesture ? '1' : '0'); | ||
1234 | } | ||
1235 | |||
1236 | static ssize_t synaptics_set_disable_gesture(struct psmouse *psmouse, | ||
1237 | void *data, const char *buf, | ||
1238 | size_t len) | ||
1239 | { | ||
1240 | struct synaptics_data *priv = psmouse->private; | ||
1241 | unsigned int value; | ||
1242 | int err; | ||
1243 | |||
1244 | err = kstrtouint(buf, 10, &value); | ||
1245 | if (err) | ||
1246 | return err; | ||
1247 | |||
1248 | if (value > 1) | ||
1249 | return -EINVAL; | ||
1250 | |||
1251 | if (value == priv->disable_gesture) | ||
1252 | return len; | ||
1253 | |||
1254 | priv->disable_gesture = value; | ||
1255 | if (value) | ||
1256 | priv->mode |= SYN_BIT_DISABLE_GESTURE; | ||
1257 | else | ||
1258 | priv->mode &= ~SYN_BIT_DISABLE_GESTURE; | ||
1259 | |||
1260 | if (synaptics_mode_cmd(psmouse, priv->mode)) | ||
1261 | return -EIO; | ||
1262 | |||
1263 | return len; | ||
1264 | } | ||
1265 | |||
1266 | PSMOUSE_DEFINE_ATTR(disable_gesture, S_IWUSR | S_IRUGO, NULL, | ||
1267 | synaptics_show_disable_gesture, | ||
1268 | synaptics_set_disable_gesture); | ||
1269 | |||
1208 | static void synaptics_disconnect(struct psmouse *psmouse) | 1270 | static void synaptics_disconnect(struct psmouse *psmouse) |
1209 | { | 1271 | { |
1272 | struct synaptics_data *priv = psmouse->private; | ||
1273 | |||
1274 | if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity)) | ||
1275 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
1276 | &psmouse_attr_disable_gesture.dattr); | ||
1277 | |||
1210 | synaptics_reset(psmouse); | 1278 | synaptics_reset(psmouse); |
1211 | kfree(psmouse->private); | 1279 | kfree(priv); |
1212 | psmouse->private = NULL; | 1280 | psmouse->private = NULL; |
1213 | } | 1281 | } |
1214 | 1282 | ||
@@ -1245,17 +1313,11 @@ static int synaptics_reconnect(struct psmouse *psmouse) | |||
1245 | return -1; | 1313 | return -1; |
1246 | } | 1314 | } |
1247 | 1315 | ||
1248 | if (synaptics_set_absolute_mode(psmouse)) { | 1316 | if (synaptics_set_mode(psmouse)) { |
1249 | psmouse_err(psmouse, "Unable to initialize device.\n"); | 1317 | psmouse_err(psmouse, "Unable to initialize device.\n"); |
1250 | return -1; | 1318 | return -1; |
1251 | } | 1319 | } |
1252 | 1320 | ||
1253 | if (synaptics_set_advanced_gesture_mode(psmouse)) { | ||
1254 | psmouse_err(psmouse, | ||
1255 | "Advanced gesture mode reconnect failed.\n"); | ||
1256 | return -1; | ||
1257 | } | ||
1258 | |||
1259 | if (old_priv.identity != priv->identity || | 1321 | if (old_priv.identity != priv->identity || |
1260 | old_priv.model_id != priv->model_id || | 1322 | old_priv.model_id != priv->model_id || |
1261 | old_priv.capabilities != priv->capabilities || | 1323 | old_priv.capabilities != priv->capabilities || |
@@ -1332,20 +1394,18 @@ void __init synaptics_module_init(void) | |||
1332 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); | 1394 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); |
1333 | } | 1395 | } |
1334 | 1396 | ||
1335 | int synaptics_init(struct psmouse *psmouse) | 1397 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) |
1336 | { | 1398 | { |
1337 | struct synaptics_data *priv; | 1399 | struct synaptics_data *priv; |
1400 | int err = -1; | ||
1338 | 1401 | ||
1339 | /* | 1402 | /* |
1340 | * The OLPC XO has issues with Synaptics' absolute mode; similarly to | 1403 | * The OLPC XO has issues with Synaptics' absolute mode; the constant |
1341 | * the HGPK, it quickly degrades and the hardware becomes jumpy and | 1404 | * packet spew overloads the EC such that key presses on the keyboard |
1342 | * overly sensitive. Not only that, but the constant packet spew | 1405 | * are missed. Given that, don't even attempt to use Absolute mode. |
1343 | * (even at a lowered 40pps rate) overloads the EC such that key | 1406 | * Relative mode seems to work just fine. |
1344 | * presses on the keyboard are missed. Given all of that, don't | ||
1345 | * even attempt to use Synaptics mode. Relative mode seems to work | ||
1346 | * just fine. | ||
1347 | */ | 1407 | */ |
1348 | if (broken_olpc_ec) { | 1408 | if (absolute_mode && broken_olpc_ec) { |
1349 | psmouse_info(psmouse, | 1409 | psmouse_info(psmouse, |
1350 | "OLPC XO detected, not enabling Synaptics protocol.\n"); | 1410 | "OLPC XO detected, not enabling Synaptics protocol.\n"); |
1351 | return -ENODEV; | 1411 | return -ENODEV; |
@@ -1362,13 +1422,12 @@ int synaptics_init(struct psmouse *psmouse) | |||
1362 | goto init_fail; | 1422 | goto init_fail; |
1363 | } | 1423 | } |
1364 | 1424 | ||
1365 | if (synaptics_set_absolute_mode(psmouse)) { | 1425 | priv->absolute_mode = absolute_mode; |
1366 | psmouse_err(psmouse, "Unable to initialize device.\n"); | 1426 | if (SYN_ID_DISGEST_SUPPORTED(priv->identity)) |
1367 | goto init_fail; | 1427 | priv->disable_gesture = true; |
1368 | } | ||
1369 | 1428 | ||
1370 | if (synaptics_set_advanced_gesture_mode(psmouse)) { | 1429 | if (synaptics_set_mode(psmouse)) { |
1371 | psmouse_err(psmouse, "Advanced gesture mode init failed.\n"); | 1430 | psmouse_err(psmouse, "Unable to initialize device.\n"); |
1372 | goto init_fail; | 1431 | goto init_fail; |
1373 | } | 1432 | } |
1374 | 1433 | ||
@@ -1393,12 +1452,19 @@ int synaptics_init(struct psmouse *psmouse) | |||
1393 | psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) | | 1452 | psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) | |
1394 | (priv->model_id & 0x000000ff); | 1453 | (priv->model_id & 0x000000ff); |
1395 | 1454 | ||
1396 | psmouse->protocol_handler = synaptics_process_byte; | 1455 | if (absolute_mode) { |
1456 | psmouse->protocol_handler = synaptics_process_byte; | ||
1457 | psmouse->pktsize = 6; | ||
1458 | } else { | ||
1459 | /* Relative mode follows standard PS/2 mouse protocol */ | ||
1460 | psmouse->protocol_handler = psmouse_process_byte; | ||
1461 | psmouse->pktsize = 3; | ||
1462 | } | ||
1463 | |||
1397 | psmouse->set_rate = synaptics_set_rate; | 1464 | psmouse->set_rate = synaptics_set_rate; |
1398 | psmouse->disconnect = synaptics_disconnect; | 1465 | psmouse->disconnect = synaptics_disconnect; |
1399 | psmouse->reconnect = synaptics_reconnect; | 1466 | psmouse->reconnect = synaptics_reconnect; |
1400 | psmouse->cleanup = synaptics_reset; | 1467 | psmouse->cleanup = synaptics_reset; |
1401 | psmouse->pktsize = 6; | ||
1402 | /* Synaptics can usually stay in sync without extra help */ | 1468 | /* Synaptics can usually stay in sync without extra help */ |
1403 | psmouse->resync_time = 0; | 1469 | psmouse->resync_time = 0; |
1404 | 1470 | ||
@@ -1417,11 +1483,32 @@ int synaptics_init(struct psmouse *psmouse) | |||
1417 | psmouse->rate = 40; | 1483 | psmouse->rate = 40; |
1418 | } | 1484 | } |
1419 | 1485 | ||
1486 | if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity)) { | ||
1487 | err = device_create_file(&psmouse->ps2dev.serio->dev, | ||
1488 | &psmouse_attr_disable_gesture.dattr); | ||
1489 | if (err) { | ||
1490 | psmouse_err(psmouse, | ||
1491 | "Failed to create disable_gesture attribute (%d)", | ||
1492 | err); | ||
1493 | goto init_fail; | ||
1494 | } | ||
1495 | } | ||
1496 | |||
1420 | return 0; | 1497 | return 0; |
1421 | 1498 | ||
1422 | init_fail: | 1499 | init_fail: |
1423 | kfree(priv); | 1500 | kfree(priv); |
1424 | return -1; | 1501 | return err; |
1502 | } | ||
1503 | |||
1504 | int synaptics_init(struct psmouse *psmouse) | ||
1505 | { | ||
1506 | return __synaptics_init(psmouse, true); | ||
1507 | } | ||
1508 | |||
1509 | int synaptics_init_relative(struct psmouse *psmouse) | ||
1510 | { | ||
1511 | return __synaptics_init(psmouse, false); | ||
1425 | } | 1512 | } |
1426 | 1513 | ||
1427 | bool synaptics_supported(void) | 1514 | bool synaptics_supported(void) |