Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Fujitsu B-series Lifebook PS/2 TouchScreen driver
0004  *
0005  * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
0006  * Copyright (c) 2005 Kenan Esau <kenan.esau@conan.de>
0007  *
0008  * TouchScreen detection, absolute mode setting and packet layout is taken from
0009  * Harald Hoyer's description of the device.
0010  */
0011 
0012 #include <linux/input.h>
0013 #include <linux/serio.h>
0014 #include <linux/libps2.h>
0015 #include <linux/dmi.h>
0016 #include <linux/slab.h>
0017 #include <linux/types.h>
0018 
0019 #include "psmouse.h"
0020 #include "lifebook.h"
0021 
0022 struct lifebook_data {
0023     struct input_dev *dev2;     /* Relative device */
0024     char phys[32];
0025 };
0026 
0027 static bool lifebook_present;
0028 
0029 static const char *desired_serio_phys;
0030 
0031 static int lifebook_limit_serio3(const struct dmi_system_id *d)
0032 {
0033     desired_serio_phys = "isa0060/serio3";
0034     return 1;
0035 }
0036 
0037 static bool lifebook_use_6byte_proto;
0038 
0039 static int lifebook_set_6byte_proto(const struct dmi_system_id *d)
0040 {
0041     lifebook_use_6byte_proto = true;
0042     return 1;
0043 }
0044 
0045 static const struct dmi_system_id lifebook_dmi_table[] __initconst = {
0046     {
0047         /* FLORA-ie 55mi */
0048         .matches = {
0049             DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"),
0050         },
0051     },
0052     {
0053         /* LifeBook B */
0054         .matches = {
0055             DMI_MATCH(DMI_PRODUCT_NAME, "Lifebook B Series"),
0056         },
0057     },
0058     {
0059         /* LifeBook B */
0060         .matches = {
0061             DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"),
0062         },
0063     },
0064     {
0065         /* Lifebook B */
0066         .matches = {
0067             DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
0068         },
0069     },
0070     {
0071         /* Lifebook B-2130 */
0072         .matches = {
0073             DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"),
0074         },
0075     },
0076     {
0077         /* Lifebook B213x/B2150 */
0078         .matches = {
0079             DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"),
0080         },
0081     },
0082     {
0083         /* Zephyr */
0084         .matches = {
0085             DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"),
0086         },
0087     },
0088     {
0089         /* Panasonic CF-18 */
0090         .matches = {
0091             DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
0092         },
0093         .callback = lifebook_limit_serio3,
0094     },
0095     {
0096         /* Panasonic CF-28 */
0097         .matches = {
0098             DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
0099             DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"),
0100         },
0101         .callback = lifebook_set_6byte_proto,
0102     },
0103     {
0104         /* Panasonic CF-29 */
0105         .matches = {
0106             DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
0107             DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
0108         },
0109         .callback = lifebook_set_6byte_proto,
0110     },
0111     {
0112         /* Panasonic CF-72 */
0113         .matches = {
0114             DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"),
0115         },
0116         .callback = lifebook_set_6byte_proto,
0117     },
0118     {
0119         /* Lifebook B142 */
0120         .matches = {
0121             DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
0122         },
0123     },
0124     { }
0125 };
0126 
0127 void __init lifebook_module_init(void)
0128 {
0129     lifebook_present = dmi_check_system(lifebook_dmi_table);
0130 }
0131 
0132 static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
0133 {
0134     struct lifebook_data *priv = psmouse->private;
0135     struct input_dev *dev1 = psmouse->dev;
0136     struct input_dev *dev2 = priv ? priv->dev2 : NULL;
0137     u8 *packet = psmouse->packet;
0138     bool relative_packet = packet[0] & 0x08;
0139 
0140     if (relative_packet || !lifebook_use_6byte_proto) {
0141         if (psmouse->pktcnt != 3)
0142             return PSMOUSE_GOOD_DATA;
0143     } else {
0144         switch (psmouse->pktcnt) {
0145         case 1:
0146             return (packet[0] & 0xf8) == 0x00 ?
0147                 PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
0148         case 2:
0149             return PSMOUSE_GOOD_DATA;
0150         case 3:
0151             return ((packet[2] & 0x30) << 2) == (packet[2] & 0xc0) ?
0152                 PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
0153         case 4:
0154             return (packet[3] & 0xf8) == 0xc0 ?
0155                 PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
0156         case 5:
0157             return (packet[4] & 0xc0) == (packet[2] & 0xc0) ?
0158                 PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
0159         case 6:
0160             if (((packet[5] & 0x30) << 2) != (packet[5] & 0xc0))
0161                 return PSMOUSE_BAD_DATA;
0162             if ((packet[5] & 0xc0) != (packet[1] & 0xc0))
0163                 return PSMOUSE_BAD_DATA;
0164             break; /* report data */
0165         }
0166     }
0167 
0168     if (relative_packet) {
0169         if (!dev2)
0170             psmouse_warn(psmouse,
0171                      "got relative packet but no relative device set up\n");
0172     } else {
0173         if (lifebook_use_6byte_proto) {
0174             input_report_abs(dev1, ABS_X,
0175                 ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f));
0176             input_report_abs(dev1, ABS_Y,
0177                 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f)));
0178         } else {
0179             input_report_abs(dev1, ABS_X,
0180                 (packet[1] | ((packet[0] & 0x30) << 4)));
0181             input_report_abs(dev1, ABS_Y,
0182                 1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
0183         }
0184         input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04);
0185         input_sync(dev1);
0186     }
0187 
0188     if (dev2) {
0189         if (relative_packet)
0190             psmouse_report_standard_motion(dev2, packet);
0191 
0192         psmouse_report_standard_buttons(dev2, packet[0]);
0193         input_sync(dev2);
0194     }
0195 
0196     return PSMOUSE_FULL_PACKET;
0197 }
0198 
0199 static int lifebook_absolute_mode(struct psmouse *psmouse)
0200 {
0201     struct ps2dev *ps2dev = &psmouse->ps2dev;
0202     u8 param;
0203     int error;
0204 
0205     error = psmouse_reset(psmouse);
0206     if (error)
0207         return error;
0208 
0209     /*
0210      * Enable absolute output -- ps2_command fails always but if
0211      * you leave this call out the touchscreen will never send
0212      * absolute coordinates
0213      */
0214     param = lifebook_use_6byte_proto ? 0x08 : 0x07;
0215     ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
0216 
0217     return 0;
0218 }
0219 
0220 static void lifebook_relative_mode(struct psmouse *psmouse)
0221 {
0222     struct ps2dev *ps2dev = &psmouse->ps2dev;
0223     u8 param = 0x06;
0224 
0225     ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
0226 }
0227 
0228 static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution)
0229 {
0230     static const u8 params[] = { 0, 1, 2, 2, 3 };
0231     u8 p;
0232 
0233     if (resolution == 0 || resolution > 400)
0234         resolution = 400;
0235 
0236     p = params[resolution / 100];
0237     ps2_command(&psmouse->ps2dev, &p, PSMOUSE_CMD_SETRES);
0238     psmouse->resolution = 50 << p;
0239 }
0240 
0241 static void lifebook_disconnect(struct psmouse *psmouse)
0242 {
0243     struct lifebook_data *priv = psmouse->private;
0244 
0245     psmouse_reset(psmouse);
0246     if (priv) {
0247         input_unregister_device(priv->dev2);
0248         kfree(priv);
0249     }
0250     psmouse->private = NULL;
0251 }
0252 
0253 int lifebook_detect(struct psmouse *psmouse, bool set_properties)
0254 {
0255     if (!lifebook_present)
0256         return -ENXIO;
0257 
0258     if (desired_serio_phys &&
0259         strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys))
0260         return -ENXIO;
0261 
0262     if (set_properties) {
0263         psmouse->vendor = "Fujitsu";
0264         psmouse->name = "Lifebook TouchScreen";
0265     }
0266 
0267     return 0;
0268 }
0269 
0270 static int lifebook_create_relative_device(struct psmouse *psmouse)
0271 {
0272     struct input_dev *dev2;
0273     struct lifebook_data *priv;
0274     int error = -ENOMEM;
0275 
0276     priv = kzalloc(sizeof(struct lifebook_data), GFP_KERNEL);
0277     dev2 = input_allocate_device();
0278     if (!priv || !dev2)
0279         goto err_out;
0280 
0281     priv->dev2 = dev2;
0282     snprintf(priv->phys, sizeof(priv->phys),
0283          "%s/input1", psmouse->ps2dev.serio->phys);
0284 
0285     dev2->phys = priv->phys;
0286     dev2->name = "LBPS/2 Fujitsu Lifebook Touchpad";
0287     dev2->id.bustype = BUS_I8042;
0288     dev2->id.vendor  = 0x0002;
0289     dev2->id.product = PSMOUSE_LIFEBOOK;
0290     dev2->id.version = 0x0000;
0291     dev2->dev.parent = &psmouse->ps2dev.serio->dev;
0292 
0293     input_set_capability(dev2, EV_REL, REL_X);
0294     input_set_capability(dev2, EV_REL, REL_Y);
0295     input_set_capability(dev2, EV_KEY, BTN_LEFT);
0296     input_set_capability(dev2, EV_KEY, BTN_RIGHT);
0297 
0298     error = input_register_device(priv->dev2);
0299     if (error)
0300         goto err_out;
0301 
0302     psmouse->private = priv;
0303     return 0;
0304 
0305  err_out:
0306     input_free_device(dev2);
0307     kfree(priv);
0308     return error;
0309 }
0310 
0311 int lifebook_init(struct psmouse *psmouse)
0312 {
0313     struct input_dev *dev1 = psmouse->dev;
0314     int max_coord = lifebook_use_6byte_proto ? 4096 : 1024;
0315     int error;
0316 
0317     error = lifebook_absolute_mode(psmouse);
0318     if (error)
0319         return error;
0320 
0321     /* Clear default capabilities */
0322     bitmap_zero(dev1->evbit, EV_CNT);
0323     bitmap_zero(dev1->relbit, REL_CNT);
0324     bitmap_zero(dev1->keybit, KEY_CNT);
0325 
0326     input_set_capability(dev1, EV_KEY, BTN_TOUCH);
0327     input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0);
0328     input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0);
0329 
0330     if (!desired_serio_phys) {
0331         error = lifebook_create_relative_device(psmouse);
0332         if (error) {
0333             lifebook_relative_mode(psmouse);
0334             return error;
0335         }
0336     }
0337 
0338     psmouse->protocol_handler = lifebook_process_byte;
0339     psmouse->set_resolution = lifebook_set_resolution;
0340     psmouse->disconnect = lifebook_disconnect;
0341     psmouse->reconnect  = lifebook_absolute_mode;
0342 
0343     psmouse->model = lifebook_use_6byte_proto ? 6 : 3;
0344 
0345     /*
0346      * Use packet size = 3 even when using 6-byte protocol because
0347      * that's what POLL will return on Lifebooks (according to spec).
0348      */
0349     psmouse->pktsize = 3;
0350 
0351     return 0;
0352 }
0353