root/drivers/input/mouse/sentelic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fsp_test_swap_cmd
  2. fsp_test_invert_cmd
  3. fsp_reg_read
  4. fsp_reg_write
  5. fsp_reg_write_enable
  6. fsp_page_reg_read
  7. fsp_page_reg_write
  8. fsp_get_version
  9. fsp_get_revision
  10. fsp_get_sn
  11. fsp_get_buttons
  12. fsp_opc_tag_enable
  13. fsp_onpad_vscr
  14. fsp_onpad_hscr
  15. fsp_attr_set_setreg
  16. fsp_attr_show_getreg
  17. fsp_attr_set_getreg
  18. fsp_attr_show_pagereg
  19. fsp_attr_set_pagereg
  20. fsp_attr_show_vscroll
  21. fsp_attr_set_vscroll
  22. fsp_attr_show_hscroll
  23. fsp_attr_set_hscroll
  24. fsp_attr_show_flags
  25. fsp_attr_set_flags
  26. fsp_attr_show_ver
  27. fsp_packet_debug
  28. fsp_packet_debug
  29. fsp_set_slot
  30. fsp_process_byte
  31. fsp_activate_protocol
  32. fsp_set_input_params
  33. fsp_detect
  34. fsp_reset
  35. fsp_disconnect
  36. fsp_reconnect
  37. fsp_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*-
   3  * Finger Sensing Pad PS/2 mouse driver.
   4  *
   5  * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
   6  * Copyright (C) 2005-2012 Tai-hwa Liang, Sentelic Corporation.
   7  */
   8 
   9 #include <linux/module.h>
  10 #include <linux/input.h>
  11 #include <linux/input/mt.h>
  12 #include <linux/ctype.h>
  13 #include <linux/libps2.h>
  14 #include <linux/serio.h>
  15 #include <linux/jiffies.h>
  16 #include <linux/slab.h>
  17 
  18 #include "psmouse.h"
  19 #include "sentelic.h"
  20 
  21 /*
  22  * Timeout for FSP PS/2 command only (in milliseconds).
  23  */
  24 #define FSP_CMD_TIMEOUT         200
  25 #define FSP_CMD_TIMEOUT2        30
  26 
  27 #define GET_ABS_X(packet)       ((packet[1] << 2) | ((packet[3] >> 2) & 0x03))
  28 #define GET_ABS_Y(packet)       ((packet[2] << 2) | (packet[3] & 0x03))
  29 
  30 /** Driver version. */
  31 static const char fsp_drv_ver[] = "1.1.0-K";
  32 
  33 /*
  34  * Make sure that the value being sent to FSP will not conflict with
  35  * possible sample rate values.
  36  */
  37 static unsigned char fsp_test_swap_cmd(unsigned char reg_val)
  38 {
  39         switch (reg_val) {
  40         case 10: case 20: case 40: case 60: case 80: case 100: case 200:
  41                 /*
  42                  * The requested value being sent to FSP matched to possible
  43                  * sample rates, swap the given value such that the hardware
  44                  * wouldn't get confused.
  45                  */
  46                 return (reg_val >> 4) | (reg_val << 4);
  47         default:
  48                 return reg_val; /* swap isn't necessary */
  49         }
  50 }
  51 
  52 /*
  53  * Make sure that the value being sent to FSP will not conflict with certain
  54  * commands.
  55  */
  56 static unsigned char fsp_test_invert_cmd(unsigned char reg_val)
  57 {
  58         switch (reg_val) {
  59         case 0xe9: case 0xee: case 0xf2: case 0xff:
  60                 /*
  61                  * The requested value being sent to FSP matched to certain
  62                  * commands, inverse the given value such that the hardware
  63                  * wouldn't get confused.
  64                  */
  65                 return ~reg_val;
  66         default:
  67                 return reg_val; /* inversion isn't necessary */
  68         }
  69 }
  70 
  71 static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val)
  72 {
  73         struct ps2dev *ps2dev = &psmouse->ps2dev;
  74         unsigned char param[3];
  75         unsigned char addr;
  76         int rc = -1;
  77 
  78         /*
  79          * We need to shut off the device and switch it into command
  80          * mode so we don't confuse our protocol handler. We don't need
  81          * to do that for writes because sysfs set helper does this for
  82          * us.
  83          */
  84         psmouse_deactivate(psmouse);
  85 
  86         ps2_begin_command(ps2dev);
  87 
  88         if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
  89                 goto out;
  90 
  91         /* should return 0xfe(request for resending) */
  92         ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
  93         /* should return 0xfc(failed) */
  94         ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
  95 
  96         if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
  97                 goto out;
  98 
  99         if ((addr = fsp_test_invert_cmd(reg_addr)) != reg_addr) {
 100                 ps2_sendbyte(ps2dev, 0x68, FSP_CMD_TIMEOUT2);
 101         } else if ((addr = fsp_test_swap_cmd(reg_addr)) != reg_addr) {
 102                 /* swapping is required */
 103                 ps2_sendbyte(ps2dev, 0xcc, FSP_CMD_TIMEOUT2);
 104                 /* expect 0xfe */
 105         } else {
 106                 /* swapping isn't necessary */
 107                 ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
 108                 /* expect 0xfe */
 109         }
 110         /* should return 0xfc(failed) */
 111         ps2_sendbyte(ps2dev, addr, FSP_CMD_TIMEOUT);
 112 
 113         if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) < 0)
 114                 goto out;
 115 
 116         *reg_val = param[2];
 117         rc = 0;
 118 
 119  out:
 120         ps2_end_command(ps2dev);
 121         psmouse_activate(psmouse);
 122         psmouse_dbg(psmouse,
 123                     "READ REG: 0x%02x is 0x%02x (rc = %d)\n",
 124                     reg_addr, *reg_val, rc);
 125         return rc;
 126 }
 127 
 128 static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val)
 129 {
 130         struct ps2dev *ps2dev = &psmouse->ps2dev;
 131         unsigned char v;
 132         int rc = -1;
 133 
 134         ps2_begin_command(ps2dev);
 135 
 136         if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
 137                 goto out;
 138 
 139         if ((v = fsp_test_invert_cmd(reg_addr)) != reg_addr) {
 140                 /* inversion is required */
 141                 ps2_sendbyte(ps2dev, 0x74, FSP_CMD_TIMEOUT2);
 142         } else {
 143                 if ((v = fsp_test_swap_cmd(reg_addr)) != reg_addr) {
 144                         /* swapping is required */
 145                         ps2_sendbyte(ps2dev, 0x77, FSP_CMD_TIMEOUT2);
 146                 } else {
 147                         /* swapping isn't necessary */
 148                         ps2_sendbyte(ps2dev, 0x55, FSP_CMD_TIMEOUT2);
 149                 }
 150         }
 151         /* write the register address in correct order */
 152         ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
 153 
 154         if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
 155                 goto out;
 156 
 157         if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
 158                 /* inversion is required */
 159                 ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2);
 160         } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) {
 161                 /* swapping is required */
 162                 ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2);
 163         } else {
 164                 /* swapping isn't necessary */
 165                 ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2);
 166         }
 167 
 168         /* write the register value in correct order */
 169         ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
 170         rc = 0;
 171 
 172  out:
 173         ps2_end_command(ps2dev);
 174         psmouse_dbg(psmouse,
 175                     "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n",
 176                     reg_addr, reg_val, rc);
 177         return rc;
 178 }
 179 
 180 /* Enable register clock gating for writing certain registers */
 181 static int fsp_reg_write_enable(struct psmouse *psmouse, bool enable)
 182 {
 183         int v, nv;
 184 
 185         if (fsp_reg_read(psmouse, FSP_REG_SYSCTL1, &v) == -1)
 186                 return -1;
 187 
 188         if (enable)
 189                 nv = v | FSP_BIT_EN_REG_CLK;
 190         else
 191                 nv = v & ~FSP_BIT_EN_REG_CLK;
 192 
 193         /* only write if necessary */
 194         if (nv != v)
 195                 if (fsp_reg_write(psmouse, FSP_REG_SYSCTL1, nv) == -1)
 196                         return -1;
 197 
 198         return 0;
 199 }
 200 
 201 static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val)
 202 {
 203         struct ps2dev *ps2dev = &psmouse->ps2dev;
 204         unsigned char param[3];
 205         int rc = -1;
 206 
 207         psmouse_deactivate(psmouse);
 208 
 209         ps2_begin_command(ps2dev);
 210 
 211         if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
 212                 goto out;
 213 
 214         ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
 215         ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
 216 
 217         if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
 218                 goto out;
 219 
 220         ps2_sendbyte(ps2dev, 0x83, FSP_CMD_TIMEOUT2);
 221         ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
 222 
 223         /* get the returned result */
 224         if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
 225                 goto out;
 226 
 227         *reg_val = param[2];
 228         rc = 0;
 229 
 230  out:
 231         ps2_end_command(ps2dev);
 232         psmouse_activate(psmouse);
 233         psmouse_dbg(psmouse,
 234                     "READ PAGE REG: 0x%02x (rc = %d)\n",
 235                     *reg_val, rc);
 236         return rc;
 237 }
 238 
 239 static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val)
 240 {
 241         struct ps2dev *ps2dev = &psmouse->ps2dev;
 242         unsigned char v;
 243         int rc = -1;
 244 
 245         ps2_begin_command(ps2dev);
 246 
 247         if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
 248                 goto out;
 249 
 250         ps2_sendbyte(ps2dev, 0x38, FSP_CMD_TIMEOUT2);
 251         ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
 252 
 253         if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
 254                 goto out;
 255 
 256         if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
 257                 ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2);
 258         } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) {
 259                 /* swapping is required */
 260                 ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2);
 261         } else {
 262                 /* swapping isn't necessary */
 263                 ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2);
 264         }
 265 
 266         ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
 267         rc = 0;
 268 
 269  out:
 270         ps2_end_command(ps2dev);
 271         psmouse_dbg(psmouse,
 272                     "WRITE PAGE REG: to 0x%02x (rc = %d)\n",
 273                     reg_val, rc);
 274         return rc;
 275 }
 276 
 277 static int fsp_get_version(struct psmouse *psmouse, int *version)
 278 {
 279         if (fsp_reg_read(psmouse, FSP_REG_VERSION, version))
 280                 return -EIO;
 281 
 282         return 0;
 283 }
 284 
 285 static int fsp_get_revision(struct psmouse *psmouse, int *rev)
 286 {
 287         if (fsp_reg_read(psmouse, FSP_REG_REVISION, rev))
 288                 return -EIO;
 289 
 290         return 0;
 291 }
 292 
 293 static int fsp_get_sn(struct psmouse *psmouse, int *sn)
 294 {
 295         int v0, v1, v2;
 296         int rc = -EIO;
 297 
 298         /* production number since Cx is available at: 0x0b40 ~ 0x0b42 */
 299         if (fsp_page_reg_write(psmouse, FSP_PAGE_0B))
 300                 goto out;
 301         if (fsp_reg_read(psmouse, FSP_REG_SN0, &v0))
 302                 goto out;
 303         if (fsp_reg_read(psmouse, FSP_REG_SN1, &v1))
 304                 goto out;
 305         if (fsp_reg_read(psmouse, FSP_REG_SN2, &v2))
 306                 goto out;
 307         *sn = (v0 << 16) | (v1 << 8) | v2;
 308         rc = 0;
 309 out:
 310         fsp_page_reg_write(psmouse, FSP_PAGE_DEFAULT);
 311         return rc;
 312 }
 313 
 314 static int fsp_get_buttons(struct psmouse *psmouse, int *btn)
 315 {
 316         static const int buttons[] = {
 317                 0x16, /* Left/Middle/Right/Forward/Backward & Scroll Up/Down */
 318                 0x06, /* Left/Middle/Right & Scroll Up/Down/Right/Left */
 319                 0x04, /* Left/Middle/Right & Scroll Up/Down */
 320                 0x02, /* Left/Middle/Right */
 321         };
 322         int val;
 323 
 324         if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS, &val) == -1)
 325                 return -EIO;
 326 
 327         *btn = buttons[(val & 0x30) >> 4];
 328         return 0;
 329 }
 330 
 331 /* Enable on-pad command tag output */
 332 static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable)
 333 {
 334         int v, nv;
 335         int res = 0;
 336 
 337         if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) {
 338                 psmouse_err(psmouse, "Unable get OPC state.\n");
 339                 return -EIO;
 340         }
 341 
 342         if (enable)
 343                 nv = v | FSP_BIT_EN_OPC_TAG;
 344         else
 345                 nv = v & ~FSP_BIT_EN_OPC_TAG;
 346 
 347         /* only write if necessary */
 348         if (nv != v) {
 349                 fsp_reg_write_enable(psmouse, true);
 350                 res = fsp_reg_write(psmouse, FSP_REG_OPC_QDOWN, nv);
 351                 fsp_reg_write_enable(psmouse, false);
 352         }
 353 
 354         if (res != 0) {
 355                 psmouse_err(psmouse, "Unable to enable OPC tag.\n");
 356                 res = -EIO;
 357         }
 358 
 359         return res;
 360 }
 361 
 362 static int fsp_onpad_vscr(struct psmouse *psmouse, bool enable)
 363 {
 364         struct fsp_data *pad = psmouse->private;
 365         int val;
 366 
 367         if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val))
 368                 return -EIO;
 369 
 370         pad->vscroll = enable;
 371 
 372         if (enable)
 373                 val |= (FSP_BIT_FIX_VSCR | FSP_BIT_ONPAD_ENABLE);
 374         else
 375                 val &= ~FSP_BIT_FIX_VSCR;
 376 
 377         if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val))
 378                 return -EIO;
 379 
 380         return 0;
 381 }
 382 
 383 static int fsp_onpad_hscr(struct psmouse *psmouse, bool enable)
 384 {
 385         struct fsp_data *pad = psmouse->private;
 386         int val, v2;
 387 
 388         if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val))
 389                 return -EIO;
 390 
 391         if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &v2))
 392                 return -EIO;
 393 
 394         pad->hscroll = enable;
 395 
 396         if (enable) {
 397                 val |= (FSP_BIT_FIX_HSCR | FSP_BIT_ONPAD_ENABLE);
 398                 v2 |= FSP_BIT_EN_MSID6;
 399         } else {
 400                 val &= ~FSP_BIT_FIX_HSCR;
 401                 v2 &= ~(FSP_BIT_EN_MSID6 | FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8);
 402         }
 403 
 404         if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val))
 405                 return -EIO;
 406 
 407         /* reconfigure horizontal scrolling packet output */
 408         if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, v2))
 409                 return -EIO;
 410 
 411         return 0;
 412 }
 413 
 414 /*
 415  * Write device specific initial parameters.
 416  *
 417  * ex: 0xab 0xcd - write oxcd into register 0xab
 418  */
 419 static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data,
 420                                    const char *buf, size_t count)
 421 {
 422         unsigned int reg, val;
 423         char *rest;
 424         ssize_t retval;
 425 
 426         reg = simple_strtoul(buf, &rest, 16);
 427         if (rest == buf || *rest != ' ' || reg > 0xff)
 428                 return -EINVAL;
 429 
 430         retval = kstrtouint(rest + 1, 16, &val);
 431         if (retval)
 432                 return retval;
 433 
 434         if (val > 0xff)
 435                 return -EINVAL;
 436 
 437         if (fsp_reg_write_enable(psmouse, true))
 438                 return -EIO;
 439 
 440         retval = fsp_reg_write(psmouse, reg, val) < 0 ? -EIO : count;
 441 
 442         fsp_reg_write_enable(psmouse, false);
 443 
 444         return count;
 445 }
 446 
 447 PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg);
 448 
 449 static ssize_t fsp_attr_show_getreg(struct psmouse *psmouse,
 450                                         void *data, char *buf)
 451 {
 452         struct fsp_data *pad = psmouse->private;
 453 
 454         return sprintf(buf, "%02x%02x\n", pad->last_reg, pad->last_val);
 455 }
 456 
 457 /*
 458  * Read a register from device.
 459  *
 460  * ex: 0xab -- read content from register 0xab
 461  */
 462 static ssize_t fsp_attr_set_getreg(struct psmouse *psmouse, void *data,
 463                                         const char *buf, size_t count)
 464 {
 465         struct fsp_data *pad = psmouse->private;
 466         unsigned int reg, val;
 467         int err;
 468 
 469         err = kstrtouint(buf, 16, &reg);
 470         if (err)
 471                 return err;
 472 
 473         if (reg > 0xff)
 474                 return -EINVAL;
 475 
 476         if (fsp_reg_read(psmouse, reg, &val))
 477                 return -EIO;
 478 
 479         pad->last_reg = reg;
 480         pad->last_val = val;
 481 
 482         return count;
 483 }
 484 
 485 PSMOUSE_DEFINE_ATTR(getreg, S_IWUSR | S_IRUGO, NULL,
 486                         fsp_attr_show_getreg, fsp_attr_set_getreg);
 487 
 488 static ssize_t fsp_attr_show_pagereg(struct psmouse *psmouse,
 489                                         void *data, char *buf)
 490 {
 491         int val = 0;
 492 
 493         if (fsp_page_reg_read(psmouse, &val))
 494                 return -EIO;
 495 
 496         return sprintf(buf, "%02x\n", val);
 497 }
 498 
 499 static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data,
 500                                         const char *buf, size_t count)
 501 {
 502         unsigned int val;
 503         int err;
 504 
 505         err = kstrtouint(buf, 16, &val);
 506         if (err)
 507                 return err;
 508 
 509         if (val > 0xff)
 510                 return -EINVAL;
 511 
 512         if (fsp_page_reg_write(psmouse, val))
 513                 return -EIO;
 514 
 515         return count;
 516 }
 517 
 518 PSMOUSE_DEFINE_ATTR(page, S_IWUSR | S_IRUGO, NULL,
 519                         fsp_attr_show_pagereg, fsp_attr_set_pagereg);
 520 
 521 static ssize_t fsp_attr_show_vscroll(struct psmouse *psmouse,
 522                                         void *data, char *buf)
 523 {
 524         struct fsp_data *pad = psmouse->private;
 525 
 526         return sprintf(buf, "%d\n", pad->vscroll);
 527 }
 528 
 529 static ssize_t fsp_attr_set_vscroll(struct psmouse *psmouse, void *data,
 530                                         const char *buf, size_t count)
 531 {
 532         unsigned int val;
 533         int err;
 534 
 535         err = kstrtouint(buf, 10, &val);
 536         if (err)
 537                 return err;
 538 
 539         if (val > 1)
 540                 return -EINVAL;
 541 
 542         fsp_onpad_vscr(psmouse, val);
 543 
 544         return count;
 545 }
 546 
 547 PSMOUSE_DEFINE_ATTR(vscroll, S_IWUSR | S_IRUGO, NULL,
 548                         fsp_attr_show_vscroll, fsp_attr_set_vscroll);
 549 
 550 static ssize_t fsp_attr_show_hscroll(struct psmouse *psmouse,
 551                                         void *data, char *buf)
 552 {
 553         struct fsp_data *pad = psmouse->private;
 554 
 555         return sprintf(buf, "%d\n", pad->hscroll);
 556 }
 557 
 558 static ssize_t fsp_attr_set_hscroll(struct psmouse *psmouse, void *data,
 559                                         const char *buf, size_t count)
 560 {
 561         unsigned int val;
 562         int err;
 563 
 564         err = kstrtouint(buf, 10, &val);
 565         if (err)
 566                 return err;
 567 
 568         if (val > 1)
 569                 return -EINVAL;
 570 
 571         fsp_onpad_hscr(psmouse, val);
 572 
 573         return count;
 574 }
 575 
 576 PSMOUSE_DEFINE_ATTR(hscroll, S_IWUSR | S_IRUGO, NULL,
 577                         fsp_attr_show_hscroll, fsp_attr_set_hscroll);
 578 
 579 static ssize_t fsp_attr_show_flags(struct psmouse *psmouse,
 580                                         void *data, char *buf)
 581 {
 582         struct fsp_data *pad = psmouse->private;
 583 
 584         return sprintf(buf, "%c\n",
 585                         pad->flags & FSPDRV_FLAG_EN_OPC ? 'C' : 'c');
 586 }
 587 
 588 static ssize_t fsp_attr_set_flags(struct psmouse *psmouse, void *data,
 589                                         const char *buf, size_t count)
 590 {
 591         struct fsp_data *pad = psmouse->private;
 592         size_t i;
 593 
 594         for (i = 0; i < count; i++) {
 595                 switch (buf[i]) {
 596                 case 'C':
 597                         pad->flags |= FSPDRV_FLAG_EN_OPC;
 598                         break;
 599                 case 'c':
 600                         pad->flags &= ~FSPDRV_FLAG_EN_OPC;
 601                         break;
 602                 default:
 603                         return -EINVAL;
 604                 }
 605         }
 606         return count;
 607 }
 608 
 609 PSMOUSE_DEFINE_ATTR(flags, S_IWUSR | S_IRUGO, NULL,
 610                         fsp_attr_show_flags, fsp_attr_set_flags);
 611 
 612 static ssize_t fsp_attr_show_ver(struct psmouse *psmouse,
 613                                         void *data, char *buf)
 614 {
 615         return sprintf(buf, "Sentelic FSP kernel module %s\n", fsp_drv_ver);
 616 }
 617 
 618 PSMOUSE_DEFINE_RO_ATTR(ver, S_IRUGO, NULL, fsp_attr_show_ver);
 619 
 620 static struct attribute *fsp_attributes[] = {
 621         &psmouse_attr_setreg.dattr.attr,
 622         &psmouse_attr_getreg.dattr.attr,
 623         &psmouse_attr_page.dattr.attr,
 624         &psmouse_attr_vscroll.dattr.attr,
 625         &psmouse_attr_hscroll.dattr.attr,
 626         &psmouse_attr_flags.dattr.attr,
 627         &psmouse_attr_ver.dattr.attr,
 628         NULL
 629 };
 630 
 631 static struct attribute_group fsp_attribute_group = {
 632         .attrs = fsp_attributes,
 633 };
 634 
 635 #ifdef  FSP_DEBUG
 636 static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[])
 637 {
 638         static unsigned int ps2_packet_cnt;
 639         static unsigned int ps2_last_second;
 640         unsigned int jiffies_msec;
 641         const char *packet_type = "UNKNOWN";
 642         unsigned short abs_x = 0, abs_y = 0;
 643 
 644         /* Interpret & dump the packet data. */
 645         switch (packet[0] >> FSP_PKT_TYPE_SHIFT) {
 646         case FSP_PKT_TYPE_ABS:
 647                 packet_type = "Absolute";
 648                 abs_x = GET_ABS_X(packet);
 649                 abs_y = GET_ABS_Y(packet);
 650                 break;
 651         case FSP_PKT_TYPE_NORMAL:
 652                 packet_type = "Normal";
 653                 break;
 654         case FSP_PKT_TYPE_NOTIFY:
 655                 packet_type = "Notify";
 656                 break;
 657         case FSP_PKT_TYPE_NORMAL_OPC:
 658                 packet_type = "Normal-OPC";
 659                 break;
 660         }
 661 
 662         ps2_packet_cnt++;
 663         jiffies_msec = jiffies_to_msecs(jiffies);
 664         psmouse_dbg(psmouse,
 665                     "%08dms %s packets: %02x, %02x, %02x, %02x; "
 666                     "abs_x: %d, abs_y: %d\n",
 667                     jiffies_msec, packet_type,
 668                     packet[0], packet[1], packet[2], packet[3], abs_x, abs_y);
 669 
 670         if (jiffies_msec - ps2_last_second > 1000) {
 671                 psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt);
 672                 ps2_packet_cnt = 0;
 673                 ps2_last_second = jiffies_msec;
 674         }
 675 }
 676 #else
 677 static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[])
 678 {
 679 }
 680 #endif
 681 
 682 static void fsp_set_slot(struct input_dev *dev, int slot, bool active,
 683                          unsigned int x, unsigned int y)
 684 {
 685         input_mt_slot(dev, slot);
 686         input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
 687         if (active) {
 688                 input_report_abs(dev, ABS_MT_POSITION_X, x);
 689                 input_report_abs(dev, ABS_MT_POSITION_Y, y);
 690         }
 691 }
 692 
 693 static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
 694 {
 695         struct input_dev *dev = psmouse->dev;
 696         struct fsp_data *ad = psmouse->private;
 697         unsigned char *packet = psmouse->packet;
 698         unsigned char button_status = 0, lscroll = 0, rscroll = 0;
 699         unsigned short abs_x, abs_y, fgrs = 0;
 700 
 701         if (psmouse->pktcnt < 4)
 702                 return PSMOUSE_GOOD_DATA;
 703 
 704         /*
 705          * Full packet accumulated, process it
 706          */
 707 
 708         fsp_packet_debug(psmouse, packet);
 709 
 710         switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) {
 711         case FSP_PKT_TYPE_ABS:
 712 
 713                 if ((packet[0] == 0x48 || packet[0] == 0x49) &&
 714                     packet[1] == 0 && packet[2] == 0) {
 715                         /*
 716                          * Ignore coordinate noise when finger leaving the
 717                          * surface, otherwise cursor may jump to upper-left
 718                          * corner.
 719                          */
 720                         packet[3] &= 0xf0;
 721                 }
 722 
 723                 abs_x = GET_ABS_X(packet);
 724                 abs_y = GET_ABS_Y(packet);
 725 
 726                 if (packet[0] & FSP_PB0_MFMC) {
 727                         /*
 728                          * MFMC packet: assume that there are two fingers on
 729                          * pad
 730                          */
 731                         fgrs = 2;
 732 
 733                         /* MFMC packet */
 734                         if (packet[0] & FSP_PB0_MFMC_FGR2) {
 735                                 /* 2nd finger */
 736                                 if (ad->last_mt_fgr == 2) {
 737                                         /*
 738                                          * workaround for buggy firmware
 739                                          * which doesn't clear MFMC bit if
 740                                          * the 1st finger is up
 741                                          */
 742                                         fgrs = 1;
 743                                         fsp_set_slot(dev, 0, false, 0, 0);
 744                                 }
 745                                 ad->last_mt_fgr = 2;
 746 
 747                                 fsp_set_slot(dev, 1, fgrs == 2, abs_x, abs_y);
 748                         } else {
 749                                 /* 1st finger */
 750                                 if (ad->last_mt_fgr == 1) {
 751                                         /*
 752                                          * workaround for buggy firmware
 753                                          * which doesn't clear MFMC bit if
 754                                          * the 2nd finger is up
 755                                          */
 756                                         fgrs = 1;
 757                                         fsp_set_slot(dev, 1, false, 0, 0);
 758                                 }
 759                                 ad->last_mt_fgr = 1;
 760                                 fsp_set_slot(dev, 0, fgrs != 0, abs_x, abs_y);
 761                         }
 762                 } else {
 763                         /* SFAC packet */
 764                         if ((packet[0] & (FSP_PB0_LBTN|FSP_PB0_PHY_BTN)) ==
 765                                 FSP_PB0_LBTN) {
 766                                 /* On-pad click in SFAC mode should be handled
 767                                  * by userspace.  On-pad clicks in MFMC mode
 768                                  * are real clickpad clicks, and not ignored.
 769                                  */
 770                                 packet[0] &= ~FSP_PB0_LBTN;
 771                         }
 772 
 773                         /* no multi-finger information */
 774                         ad->last_mt_fgr = 0;
 775 
 776                         if (abs_x != 0 && abs_y != 0)
 777                                 fgrs = 1;
 778 
 779                         fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y);
 780                         fsp_set_slot(dev, 1, false, 0, 0);
 781                 }
 782                 if (fgrs == 1 || (fgrs == 2 && !(packet[0] & FSP_PB0_MFMC_FGR2))) {
 783                         input_report_abs(dev, ABS_X, abs_x);
 784                         input_report_abs(dev, ABS_Y, abs_y);
 785                 }
 786                 input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
 787                 input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
 788                 input_report_key(dev, BTN_TOUCH, fgrs);
 789                 input_report_key(dev, BTN_TOOL_FINGER, fgrs == 1);
 790                 input_report_key(dev, BTN_TOOL_DOUBLETAP, fgrs == 2);
 791                 break;
 792 
 793         case FSP_PKT_TYPE_NORMAL_OPC:
 794                 /* on-pad click, filter it if necessary */
 795                 if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC)
 796                         packet[0] &= ~FSP_PB0_LBTN;
 797                 /* fall through */
 798 
 799         case FSP_PKT_TYPE_NORMAL:
 800                 /* normal packet */
 801                 /* special packet data translation from on-pad packets */
 802                 if (packet[3] != 0) {
 803                         if (packet[3] & BIT(0))
 804                                 button_status |= 0x01;  /* wheel down */
 805                         if (packet[3] & BIT(1))
 806                                 button_status |= 0x0f;  /* wheel up */
 807                         if (packet[3] & BIT(2))
 808                                 button_status |= BIT(4);/* horizontal left */
 809                         if (packet[3] & BIT(3))
 810                                 button_status |= BIT(5);/* horizontal right */
 811                         /* push back to packet queue */
 812                         if (button_status != 0)
 813                                 packet[3] = button_status;
 814                         rscroll = (packet[3] >> 4) & 1;
 815                         lscroll = (packet[3] >> 5) & 1;
 816                 }
 817                 /*
 818                  * Processing wheel up/down and extra button events
 819                  */
 820                 input_report_rel(dev, REL_WHEEL,
 821                                  (int)(packet[3] & 8) - (int)(packet[3] & 7));
 822                 input_report_rel(dev, REL_HWHEEL, lscroll - rscroll);
 823                 input_report_key(dev, BTN_BACK, lscroll);
 824                 input_report_key(dev, BTN_FORWARD, rscroll);
 825 
 826                 /*
 827                  * Standard PS/2 Mouse
 828                  */
 829                 psmouse_report_standard_packet(dev, packet);
 830                 break;
 831         }
 832 
 833         input_sync(dev);
 834 
 835         return PSMOUSE_FULL_PACKET;
 836 }
 837 
 838 static int fsp_activate_protocol(struct psmouse *psmouse)
 839 {
 840         struct fsp_data *pad = psmouse->private;
 841         struct ps2dev *ps2dev = &psmouse->ps2dev;
 842         unsigned char param[2];
 843         int val;
 844 
 845         /*
 846          * Standard procedure to enter FSP Intellimouse mode
 847          * (scrolling wheel, 4th and 5th buttons)
 848          */
 849         param[0] = 200;
 850         ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
 851         param[0] = 200;
 852         ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
 853         param[0] =  80;
 854         ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
 855 
 856         ps2_command(ps2dev, param, PSMOUSE_CMD_GETID);
 857         if (param[0] != 0x04) {
 858                 psmouse_err(psmouse,
 859                             "Unable to enable 4 bytes packet format.\n");
 860                 return -EIO;
 861         }
 862 
 863         if (pad->ver < FSP_VER_STL3888_C0) {
 864                 /* Preparing relative coordinates output for older hardware */
 865                 if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) {
 866                         psmouse_err(psmouse,
 867                                     "Unable to read SYSCTL5 register.\n");
 868                         return -EIO;
 869                 }
 870 
 871                 if (fsp_get_buttons(psmouse, &pad->buttons)) {
 872                         psmouse_err(psmouse,
 873                                     "Unable to retrieve number of buttons.\n");
 874                         return -EIO;
 875                 }
 876 
 877                 val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8);
 878                 /* Ensure we are not in absolute mode */
 879                 val &= ~FSP_BIT_EN_PKT_G0;
 880                 if (pad->buttons == 0x06) {
 881                         /* Left/Middle/Right & Scroll Up/Down/Right/Left */
 882                         val |= FSP_BIT_EN_MSID6;
 883                 }
 884 
 885                 if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) {
 886                         psmouse_err(psmouse,
 887                                     "Unable to set up required mode bits.\n");
 888                         return -EIO;
 889                 }
 890 
 891                 /*
 892                  * Enable OPC tags such that driver can tell the difference
 893                  * between on-pad and real button click
 894                  */
 895                 if (fsp_opc_tag_enable(psmouse, true))
 896                         psmouse_warn(psmouse,
 897                                      "Failed to enable OPC tag mode.\n");
 898                 /* enable on-pad click by default */
 899                 pad->flags |= FSPDRV_FLAG_EN_OPC;
 900 
 901                 /* Enable on-pad vertical and horizontal scrolling */
 902                 fsp_onpad_vscr(psmouse, true);
 903                 fsp_onpad_hscr(psmouse, true);
 904         } else {
 905                 /* Enable absolute coordinates output for Cx/Dx hardware */
 906                 if (fsp_reg_write(psmouse, FSP_REG_SWC1,
 907                                   FSP_BIT_SWC1_EN_ABS_1F |
 908                                   FSP_BIT_SWC1_EN_ABS_2F |
 909                                   FSP_BIT_SWC1_EN_FUP_OUT |
 910                                   FSP_BIT_SWC1_EN_ABS_CON)) {
 911                         psmouse_err(psmouse,
 912                                     "Unable to enable absolute coordinates output.\n");
 913                         return -EIO;
 914                 }
 915         }
 916 
 917         return 0;
 918 }
 919 
 920 static int fsp_set_input_params(struct psmouse *psmouse)
 921 {
 922         struct input_dev *dev = psmouse->dev;
 923         struct fsp_data *pad = psmouse->private;
 924 
 925         if (pad->ver < FSP_VER_STL3888_C0) {
 926                 __set_bit(BTN_MIDDLE, dev->keybit);
 927                 __set_bit(BTN_BACK, dev->keybit);
 928                 __set_bit(BTN_FORWARD, dev->keybit);
 929                 __set_bit(REL_WHEEL, dev->relbit);
 930                 __set_bit(REL_HWHEEL, dev->relbit);
 931         } else {
 932                 /*
 933                  * Hardware prior to Cx performs much better in relative mode;
 934                  * hence, only enable absolute coordinates output as well as
 935                  * multi-touch output for the newer hardware.
 936                  *
 937                  * Maximum coordinates can be computed as:
 938                  *
 939                  *      number of scanlines * 64 - 57
 940                  *
 941                  * where number of X/Y scanline lines are 16/12.
 942                  */
 943                 int abs_x = 967, abs_y = 711;
 944 
 945                 __set_bit(EV_ABS, dev->evbit);
 946                 __clear_bit(EV_REL, dev->evbit);
 947                 __set_bit(BTN_TOUCH, dev->keybit);
 948                 __set_bit(BTN_TOOL_FINGER, dev->keybit);
 949                 __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
 950                 __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
 951 
 952                 input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0);
 953                 input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0);
 954                 input_mt_init_slots(dev, 2, 0);
 955                 input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0);
 956                 input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0);
 957         }
 958 
 959         return 0;
 960 }
 961 
 962 int fsp_detect(struct psmouse *psmouse, bool set_properties)
 963 {
 964         int id;
 965 
 966         if (fsp_reg_read(psmouse, FSP_REG_DEVICE_ID, &id))
 967                 return -EIO;
 968 
 969         if (id != 0x01)
 970                 return -ENODEV;
 971 
 972         if (set_properties) {
 973                 psmouse->vendor = "Sentelic";
 974                 psmouse->name = "FingerSensingPad";
 975         }
 976 
 977         return 0;
 978 }
 979 
 980 static void fsp_reset(struct psmouse *psmouse)
 981 {
 982         fsp_opc_tag_enable(psmouse, false);
 983         fsp_onpad_vscr(psmouse, false);
 984         fsp_onpad_hscr(psmouse, false);
 985 }
 986 
 987 static void fsp_disconnect(struct psmouse *psmouse)
 988 {
 989         sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
 990                            &fsp_attribute_group);
 991 
 992         fsp_reset(psmouse);
 993         kfree(psmouse->private);
 994 }
 995 
 996 static int fsp_reconnect(struct psmouse *psmouse)
 997 {
 998         int version;
 999 
1000         if (fsp_detect(psmouse, 0))
1001                 return -ENODEV;
1002 
1003         if (fsp_get_version(psmouse, &version))
1004                 return -ENODEV;
1005 
1006         if (fsp_activate_protocol(psmouse))
1007                 return -EIO;
1008 
1009         return 0;
1010 }
1011 
1012 int fsp_init(struct psmouse *psmouse)
1013 {
1014         struct fsp_data *priv;
1015         int ver, rev, sn = 0;
1016         int error;
1017 
1018         if (fsp_get_version(psmouse, &ver) ||
1019             fsp_get_revision(psmouse, &rev)) {
1020                 return -ENODEV;
1021         }
1022         if (ver >= FSP_VER_STL3888_C0) {
1023                 /* firmware information is only available since C0 */
1024                 fsp_get_sn(psmouse, &sn);
1025         }
1026 
1027         psmouse_info(psmouse,
1028                      "Finger Sensing Pad, hw: %d.%d.%d, sn: %x, sw: %s\n",
1029                      ver >> 4, ver & 0x0F, rev, sn, fsp_drv_ver);
1030 
1031         psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL);
1032         if (!priv)
1033                 return -ENOMEM;
1034 
1035         priv->ver = ver;
1036         priv->rev = rev;
1037 
1038         psmouse->protocol_handler = fsp_process_byte;
1039         psmouse->disconnect = fsp_disconnect;
1040         psmouse->reconnect = fsp_reconnect;
1041         psmouse->cleanup = fsp_reset;
1042         psmouse->pktsize = 4;
1043 
1044         error = fsp_activate_protocol(psmouse);
1045         if (error)
1046                 goto err_out;
1047 
1048         /* Set up various supported input event bits */
1049         error = fsp_set_input_params(psmouse);
1050         if (error)
1051                 goto err_out;
1052 
1053         error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
1054                                    &fsp_attribute_group);
1055         if (error) {
1056                 psmouse_err(psmouse,
1057                             "Failed to create sysfs attributes (%d)", error);
1058                 goto err_out;
1059         }
1060 
1061         return 0;
1062 
1063  err_out:
1064         kfree(psmouse->private);
1065         psmouse->private = NULL;
1066         return error;
1067 }

/* [<][>][^][v][top][bottom][index][help] */