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