18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Fujitsu B-series Lifebook PS/2 TouchScreen driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> 68c2ecf20Sopenharmony_ci * Copyright (c) 2005 Kenan Esau <kenan.esau@conan.de> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * TouchScreen detection, absolute mode setting and packet layout is taken from 98c2ecf20Sopenharmony_ci * Harald Hoyer's description of the device. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/input.h> 138c2ecf20Sopenharmony_ci#include <linux/serio.h> 148c2ecf20Sopenharmony_ci#include <linux/libps2.h> 158c2ecf20Sopenharmony_ci#include <linux/dmi.h> 168c2ecf20Sopenharmony_ci#include <linux/slab.h> 178c2ecf20Sopenharmony_ci#include <linux/types.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "psmouse.h" 208c2ecf20Sopenharmony_ci#include "lifebook.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistruct lifebook_data { 238c2ecf20Sopenharmony_ci struct input_dev *dev2; /* Relative device */ 248c2ecf20Sopenharmony_ci char phys[32]; 258c2ecf20Sopenharmony_ci}; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic bool lifebook_present; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic const char *desired_serio_phys; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic int lifebook_limit_serio3(const struct dmi_system_id *d) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci desired_serio_phys = "isa0060/serio3"; 348c2ecf20Sopenharmony_ci return 1; 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic bool lifebook_use_6byte_proto; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic int lifebook_set_6byte_proto(const struct dmi_system_id *d) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci lifebook_use_6byte_proto = true; 428c2ecf20Sopenharmony_ci return 1; 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic const struct dmi_system_id lifebook_dmi_table[] __initconst = { 468c2ecf20Sopenharmony_ci { 478c2ecf20Sopenharmony_ci /* FLORA-ie 55mi */ 488c2ecf20Sopenharmony_ci .matches = { 498c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"), 508c2ecf20Sopenharmony_ci }, 518c2ecf20Sopenharmony_ci }, 528c2ecf20Sopenharmony_ci { 538c2ecf20Sopenharmony_ci /* LifeBook B */ 548c2ecf20Sopenharmony_ci .matches = { 558c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Lifebook B Series"), 568c2ecf20Sopenharmony_ci }, 578c2ecf20Sopenharmony_ci }, 588c2ecf20Sopenharmony_ci { 598c2ecf20Sopenharmony_ci /* LifeBook B */ 608c2ecf20Sopenharmony_ci .matches = { 618c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"), 628c2ecf20Sopenharmony_ci }, 638c2ecf20Sopenharmony_ci }, 648c2ecf20Sopenharmony_ci { 658c2ecf20Sopenharmony_ci /* Lifebook B */ 668c2ecf20Sopenharmony_ci .matches = { 678c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), 688c2ecf20Sopenharmony_ci }, 698c2ecf20Sopenharmony_ci }, 708c2ecf20Sopenharmony_ci { 718c2ecf20Sopenharmony_ci /* Lifebook B-2130 */ 728c2ecf20Sopenharmony_ci .matches = { 738c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"), 748c2ecf20Sopenharmony_ci }, 758c2ecf20Sopenharmony_ci }, 768c2ecf20Sopenharmony_ci { 778c2ecf20Sopenharmony_ci /* Lifebook B213x/B2150 */ 788c2ecf20Sopenharmony_ci .matches = { 798c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), 808c2ecf20Sopenharmony_ci }, 818c2ecf20Sopenharmony_ci }, 828c2ecf20Sopenharmony_ci { 838c2ecf20Sopenharmony_ci /* Zephyr */ 848c2ecf20Sopenharmony_ci .matches = { 858c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"), 868c2ecf20Sopenharmony_ci }, 878c2ecf20Sopenharmony_ci }, 888c2ecf20Sopenharmony_ci { 898c2ecf20Sopenharmony_ci /* Panasonic CF-18 */ 908c2ecf20Sopenharmony_ci .matches = { 918c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"), 928c2ecf20Sopenharmony_ci }, 938c2ecf20Sopenharmony_ci .callback = lifebook_limit_serio3, 948c2ecf20Sopenharmony_ci }, 958c2ecf20Sopenharmony_ci { 968c2ecf20Sopenharmony_ci /* Panasonic CF-28 */ 978c2ecf20Sopenharmony_ci .matches = { 988c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), 998c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"), 1008c2ecf20Sopenharmony_ci }, 1018c2ecf20Sopenharmony_ci .callback = lifebook_set_6byte_proto, 1028c2ecf20Sopenharmony_ci }, 1038c2ecf20Sopenharmony_ci { 1048c2ecf20Sopenharmony_ci /* Panasonic CF-29 */ 1058c2ecf20Sopenharmony_ci .matches = { 1068c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), 1078c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"), 1088c2ecf20Sopenharmony_ci }, 1098c2ecf20Sopenharmony_ci .callback = lifebook_set_6byte_proto, 1108c2ecf20Sopenharmony_ci }, 1118c2ecf20Sopenharmony_ci { 1128c2ecf20Sopenharmony_ci /* Panasonic CF-72 */ 1138c2ecf20Sopenharmony_ci .matches = { 1148c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"), 1158c2ecf20Sopenharmony_ci }, 1168c2ecf20Sopenharmony_ci .callback = lifebook_set_6byte_proto, 1178c2ecf20Sopenharmony_ci }, 1188c2ecf20Sopenharmony_ci { 1198c2ecf20Sopenharmony_ci /* Lifebook B142 */ 1208c2ecf20Sopenharmony_ci .matches = { 1218c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), 1228c2ecf20Sopenharmony_ci }, 1238c2ecf20Sopenharmony_ci }, 1248c2ecf20Sopenharmony_ci { } 1258c2ecf20Sopenharmony_ci}; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_civoid __init lifebook_module_init(void) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci lifebook_present = dmi_check_system(lifebook_dmi_table); 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci struct lifebook_data *priv = psmouse->private; 1358c2ecf20Sopenharmony_ci struct input_dev *dev1 = psmouse->dev; 1368c2ecf20Sopenharmony_ci struct input_dev *dev2 = priv ? priv->dev2 : NULL; 1378c2ecf20Sopenharmony_ci u8 *packet = psmouse->packet; 1388c2ecf20Sopenharmony_ci bool relative_packet = packet[0] & 0x08; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (relative_packet || !lifebook_use_6byte_proto) { 1418c2ecf20Sopenharmony_ci if (psmouse->pktcnt != 3) 1428c2ecf20Sopenharmony_ci return PSMOUSE_GOOD_DATA; 1438c2ecf20Sopenharmony_ci } else { 1448c2ecf20Sopenharmony_ci switch (psmouse->pktcnt) { 1458c2ecf20Sopenharmony_ci case 1: 1468c2ecf20Sopenharmony_ci return (packet[0] & 0xf8) == 0x00 ? 1478c2ecf20Sopenharmony_ci PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; 1488c2ecf20Sopenharmony_ci case 2: 1498c2ecf20Sopenharmony_ci return PSMOUSE_GOOD_DATA; 1508c2ecf20Sopenharmony_ci case 3: 1518c2ecf20Sopenharmony_ci return ((packet[2] & 0x30) << 2) == (packet[2] & 0xc0) ? 1528c2ecf20Sopenharmony_ci PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; 1538c2ecf20Sopenharmony_ci case 4: 1548c2ecf20Sopenharmony_ci return (packet[3] & 0xf8) == 0xc0 ? 1558c2ecf20Sopenharmony_ci PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; 1568c2ecf20Sopenharmony_ci case 5: 1578c2ecf20Sopenharmony_ci return (packet[4] & 0xc0) == (packet[2] & 0xc0) ? 1588c2ecf20Sopenharmony_ci PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; 1598c2ecf20Sopenharmony_ci case 6: 1608c2ecf20Sopenharmony_ci if (((packet[5] & 0x30) << 2) != (packet[5] & 0xc0)) 1618c2ecf20Sopenharmony_ci return PSMOUSE_BAD_DATA; 1628c2ecf20Sopenharmony_ci if ((packet[5] & 0xc0) != (packet[1] & 0xc0)) 1638c2ecf20Sopenharmony_ci return PSMOUSE_BAD_DATA; 1648c2ecf20Sopenharmony_ci break; /* report data */ 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci if (relative_packet) { 1698c2ecf20Sopenharmony_ci if (!dev2) 1708c2ecf20Sopenharmony_ci psmouse_warn(psmouse, 1718c2ecf20Sopenharmony_ci "got relative packet but no relative device set up\n"); 1728c2ecf20Sopenharmony_ci } else { 1738c2ecf20Sopenharmony_ci if (lifebook_use_6byte_proto) { 1748c2ecf20Sopenharmony_ci input_report_abs(dev1, ABS_X, 1758c2ecf20Sopenharmony_ci ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f)); 1768c2ecf20Sopenharmony_ci input_report_abs(dev1, ABS_Y, 1778c2ecf20Sopenharmony_ci 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f))); 1788c2ecf20Sopenharmony_ci } else { 1798c2ecf20Sopenharmony_ci input_report_abs(dev1, ABS_X, 1808c2ecf20Sopenharmony_ci (packet[1] | ((packet[0] & 0x30) << 4))); 1818c2ecf20Sopenharmony_ci input_report_abs(dev1, ABS_Y, 1828c2ecf20Sopenharmony_ci 1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04); 1858c2ecf20Sopenharmony_ci input_sync(dev1); 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (dev2) { 1898c2ecf20Sopenharmony_ci if (relative_packet) 1908c2ecf20Sopenharmony_ci psmouse_report_standard_motion(dev2, packet); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci psmouse_report_standard_buttons(dev2, packet[0]); 1938c2ecf20Sopenharmony_ci input_sync(dev2); 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci return PSMOUSE_FULL_PACKET; 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic int lifebook_absolute_mode(struct psmouse *psmouse) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci struct ps2dev *ps2dev = &psmouse->ps2dev; 2028c2ecf20Sopenharmony_ci u8 param; 2038c2ecf20Sopenharmony_ci int error; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci error = psmouse_reset(psmouse); 2068c2ecf20Sopenharmony_ci if (error) 2078c2ecf20Sopenharmony_ci return error; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci /* 2108c2ecf20Sopenharmony_ci * Enable absolute output -- ps2_command fails always but if 2118c2ecf20Sopenharmony_ci * you leave this call out the touchscreen will never send 2128c2ecf20Sopenharmony_ci * absolute coordinates 2138c2ecf20Sopenharmony_ci */ 2148c2ecf20Sopenharmony_ci param = lifebook_use_6byte_proto ? 0x08 : 0x07; 2158c2ecf20Sopenharmony_ci ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci return 0; 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic void lifebook_relative_mode(struct psmouse *psmouse) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci struct ps2dev *ps2dev = &psmouse->ps2dev; 2238c2ecf20Sopenharmony_ci u8 param = 0x06; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci static const u8 params[] = { 0, 1, 2, 2, 3 }; 2318c2ecf20Sopenharmony_ci u8 p; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci if (resolution == 0 || resolution > 400) 2348c2ecf20Sopenharmony_ci resolution = 400; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci p = params[resolution / 100]; 2378c2ecf20Sopenharmony_ci ps2_command(&psmouse->ps2dev, &p, PSMOUSE_CMD_SETRES); 2388c2ecf20Sopenharmony_ci psmouse->resolution = 50 << p; 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic void lifebook_disconnect(struct psmouse *psmouse) 2428c2ecf20Sopenharmony_ci{ 2438c2ecf20Sopenharmony_ci struct lifebook_data *priv = psmouse->private; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci psmouse_reset(psmouse); 2468c2ecf20Sopenharmony_ci if (priv) { 2478c2ecf20Sopenharmony_ci input_unregister_device(priv->dev2); 2488c2ecf20Sopenharmony_ci kfree(priv); 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci psmouse->private = NULL; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ciint lifebook_detect(struct psmouse *psmouse, bool set_properties) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci if (!lifebook_present) 2568c2ecf20Sopenharmony_ci return -ENXIO; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci if (desired_serio_phys && 2598c2ecf20Sopenharmony_ci strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys)) 2608c2ecf20Sopenharmony_ci return -ENXIO; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci if (set_properties) { 2638c2ecf20Sopenharmony_ci psmouse->vendor = "Fujitsu"; 2648c2ecf20Sopenharmony_ci psmouse->name = "Lifebook TouchScreen"; 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci return 0; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic int lifebook_create_relative_device(struct psmouse *psmouse) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci struct input_dev *dev2; 2738c2ecf20Sopenharmony_ci struct lifebook_data *priv; 2748c2ecf20Sopenharmony_ci int error = -ENOMEM; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci priv = kzalloc(sizeof(struct lifebook_data), GFP_KERNEL); 2778c2ecf20Sopenharmony_ci dev2 = input_allocate_device(); 2788c2ecf20Sopenharmony_ci if (!priv || !dev2) 2798c2ecf20Sopenharmony_ci goto err_out; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci priv->dev2 = dev2; 2828c2ecf20Sopenharmony_ci snprintf(priv->phys, sizeof(priv->phys), 2838c2ecf20Sopenharmony_ci "%s/input1", psmouse->ps2dev.serio->phys); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci dev2->phys = priv->phys; 2868c2ecf20Sopenharmony_ci dev2->name = "LBPS/2 Fujitsu Lifebook Touchpad"; 2878c2ecf20Sopenharmony_ci dev2->id.bustype = BUS_I8042; 2888c2ecf20Sopenharmony_ci dev2->id.vendor = 0x0002; 2898c2ecf20Sopenharmony_ci dev2->id.product = PSMOUSE_LIFEBOOK; 2908c2ecf20Sopenharmony_ci dev2->id.version = 0x0000; 2918c2ecf20Sopenharmony_ci dev2->dev.parent = &psmouse->ps2dev.serio->dev; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci input_set_capability(dev2, EV_REL, REL_X); 2948c2ecf20Sopenharmony_ci input_set_capability(dev2, EV_REL, REL_Y); 2958c2ecf20Sopenharmony_ci input_set_capability(dev2, EV_KEY, BTN_LEFT); 2968c2ecf20Sopenharmony_ci input_set_capability(dev2, EV_KEY, BTN_RIGHT); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci error = input_register_device(priv->dev2); 2998c2ecf20Sopenharmony_ci if (error) 3008c2ecf20Sopenharmony_ci goto err_out; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci psmouse->private = priv; 3038c2ecf20Sopenharmony_ci return 0; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci err_out: 3068c2ecf20Sopenharmony_ci input_free_device(dev2); 3078c2ecf20Sopenharmony_ci kfree(priv); 3088c2ecf20Sopenharmony_ci return error; 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ciint lifebook_init(struct psmouse *psmouse) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci struct input_dev *dev1 = psmouse->dev; 3148c2ecf20Sopenharmony_ci int max_coord = lifebook_use_6byte_proto ? 4096 : 1024; 3158c2ecf20Sopenharmony_ci int error; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci error = lifebook_absolute_mode(psmouse); 3188c2ecf20Sopenharmony_ci if (error) 3198c2ecf20Sopenharmony_ci return error; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* Clear default capabilities */ 3228c2ecf20Sopenharmony_ci bitmap_zero(dev1->evbit, EV_CNT); 3238c2ecf20Sopenharmony_ci bitmap_zero(dev1->relbit, REL_CNT); 3248c2ecf20Sopenharmony_ci bitmap_zero(dev1->keybit, KEY_CNT); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci input_set_capability(dev1, EV_KEY, BTN_TOUCH); 3278c2ecf20Sopenharmony_ci input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0); 3288c2ecf20Sopenharmony_ci input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (!desired_serio_phys) { 3318c2ecf20Sopenharmony_ci error = lifebook_create_relative_device(psmouse); 3328c2ecf20Sopenharmony_ci if (error) { 3338c2ecf20Sopenharmony_ci lifebook_relative_mode(psmouse); 3348c2ecf20Sopenharmony_ci return error; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci psmouse->protocol_handler = lifebook_process_byte; 3398c2ecf20Sopenharmony_ci psmouse->set_resolution = lifebook_set_resolution; 3408c2ecf20Sopenharmony_ci psmouse->disconnect = lifebook_disconnect; 3418c2ecf20Sopenharmony_ci psmouse->reconnect = lifebook_absolute_mode; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci psmouse->model = lifebook_use_6byte_proto ? 6 : 3; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* 3468c2ecf20Sopenharmony_ci * Use packet size = 3 even when using 6-byte protocol because 3478c2ecf20Sopenharmony_ci * that's what POLL will return on Lifebooks (according to spec). 3488c2ecf20Sopenharmony_ci */ 3498c2ecf20Sopenharmony_ci psmouse->pktsize = 3; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci return 0; 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 354