1 /*- 2 * Finger Sensing Pad PS/2 mouse driver. 3 * 4 * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. 5 * Copyright (C) 2005-2009 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/version.h> 24 #include <linux/input.h> 25 #include <linux/ctype.h> 26 #include <linux/libps2.h> 27 #include <linux/serio.h> 28 #include <linux/jiffies.h> 29 30 #include "psmouse.h" 31 #include "sentelic.h" 32 33 /* 34 * Timeout for FSP PS/2 command only (in milliseconds). 35 */ 36 #define FSP_CMD_TIMEOUT 200 37 #define FSP_CMD_TIMEOUT2 30 38 39 /** Driver version. */ 40 static const char fsp_drv_ver[] = "1.0.0-K"; 41 42 /* 43 * Make sure that the value being sent to FSP will not conflict with 44 * possible sample rate values. 45 */ 46 static unsigned char fsp_test_swap_cmd(unsigned char reg_val) 47 { 48 switch (reg_val) { 49 case 10: case 20: case 40: case 60: case 80: case 100: case 200: 50 /* 51 * The requested value being sent to FSP matched to possible 52 * sample rates, swap the given value such that the hardware 53 * wouldn't get confused. 54 */ 55 return (reg_val >> 4) | (reg_val << 4); 56 default: 57 return reg_val; /* swap isn't necessary */ 58 } 59 } 60 61 /* 62 * Make sure that the value being sent to FSP will not conflict with certain 63 * commands. 64 */ 65 static unsigned char fsp_test_invert_cmd(unsigned char reg_val) 66 { 67 switch (reg_val) { 68 case 0xe9: case 0xee: case 0xf2: case 0xff: 69 /* 70 * The requested value being sent to FSP matched to certain 71 * commands, inverse the given value such that the hardware 72 * wouldn't get confused. 73 */ 74 return ~reg_val; 75 default: 76 return reg_val; /* inversion isn't necessary */ 77 } 78 } 79 80 static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) 81 { 82 struct ps2dev *ps2dev = &psmouse->ps2dev; 83 unsigned char param[3]; 84 unsigned char addr; 85 int rc = -1; 86 87 /* 88 * We need to shut off the device and switch it into command 89 * mode so we don't confuse our protocol handler. We don't need 90 * to do that for writes because sysfs set helper does this for 91 * us. 92 */ 93 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); 94 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); 95 mutex_lock(&ps2dev->cmd_mutex); 96 97 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) 98 goto out; 99 100 /* should return 0xfe(request for resending) */ 101 ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); 102 /* should return 0xfc(failed) */ 103 ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); 104 105 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) 106 goto out; 107 108 if ((addr = fsp_test_invert_cmd(reg_addr)) != reg_addr) { 109 ps2_sendbyte(ps2dev, 0x68, FSP_CMD_TIMEOUT2); 110 } else if ((addr = fsp_test_swap_cmd(reg_addr)) != reg_addr) { 111 /* swapping is required */ 112 ps2_sendbyte(ps2dev, 0xcc, FSP_CMD_TIMEOUT2); 113 /* expect 0xfe */ 114 } else { 115 /* swapping isn't necessary */ 116 ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); 117 /* expect 0xfe */ 118 } 119 /* should return 0xfc(failed) */ 120 ps2_sendbyte(ps2dev, addr, FSP_CMD_TIMEOUT); 121 122 if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) < 0) 123 goto out; 124 125 *reg_val = param[2]; 126 rc = 0; 127 128 out: 129 mutex_unlock(&ps2dev->cmd_mutex); 130 ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); 131 psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); 132 dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", 133 reg_addr, *reg_val, rc); 134 return rc; 135 } 136 137 static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) 138 { 139 struct ps2dev *ps2dev = &psmouse->ps2dev; 140 unsigned char v; 141 int rc = -1; 142 143 mutex_lock(&ps2dev->cmd_mutex); 144 145 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) 146 goto out; 147 148 if ((v = fsp_test_invert_cmd(reg_addr)) != reg_addr) { 149 /* inversion is required */ 150 ps2_sendbyte(ps2dev, 0x74, FSP_CMD_TIMEOUT2); 151 } else { 152 if ((v = fsp_test_swap_cmd(reg_addr)) != reg_addr) { 153 /* swapping is required */ 154 ps2_sendbyte(ps2dev, 0x77, FSP_CMD_TIMEOUT2); 155 } else { 156 /* swapping isn't necessary */ 157 ps2_sendbyte(ps2dev, 0x55, FSP_CMD_TIMEOUT2); 158 } 159 } 160 /* write the register address in correct order */ 161 ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); 162 163 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) 164 return -1; 165 166 if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) { 167 /* inversion is required */ 168 ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2); 169 } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) { 170 /* swapping is required */ 171 ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2); 172 } else { 173 /* swapping isn't necessary */ 174 ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2); 175 } 176 177 /* write the register value in correct order */ 178 ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); 179 rc = 0; 180 181 out: 182 mutex_unlock(&ps2dev->cmd_mutex); 183 dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", 184 reg_addr, reg_val, rc); 185 return rc; 186 } 187 188 /* Enable register clock gating for writing certain registers */ 189 static int fsp_reg_write_enable(struct psmouse *psmouse, bool enable) 190 { 191 int v, nv; 192 193 if (fsp_reg_read(psmouse, FSP_REG_SYSCTL1, &v) == -1) 194 return -1; 195 196 if (enable) 197 nv = v | FSP_BIT_EN_REG_CLK; 198 else 199 nv = v & ~FSP_BIT_EN_REG_CLK; 200 201 /* only write if necessary */ 202 if (nv != v) 203 if (fsp_reg_write(psmouse, FSP_REG_SYSCTL1, nv) == -1) 204 return -1; 205 206 return 0; 207 } 208 209 static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) 210 { 211 struct ps2dev *ps2dev = &psmouse->ps2dev; 212 unsigned char param[3]; 213 int rc = -1; 214 215 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); 216 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); 217 mutex_lock(&ps2dev->cmd_mutex); 218 219 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) 220 goto out; 221 222 ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); 223 ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); 224 225 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) 226 goto out; 227 228 ps2_sendbyte(ps2dev, 0x83, FSP_CMD_TIMEOUT2); 229 ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); 230 231 /* get the returned result */ 232 if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) 233 goto out; 234 235 *reg_val = param[2]; 236 rc = 0; 237 238 out: 239 mutex_unlock(&ps2dev->cmd_mutex); 240 ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); 241 psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); 242 dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", 243 *reg_val, rc); 244 return rc; 245 } 246 247 static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) 248 { 249 struct ps2dev *ps2dev = &psmouse->ps2dev; 250 unsigned char v; 251 int rc = -1; 252 253 mutex_lock(&ps2dev->cmd_mutex); 254 255 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) 256 goto out; 257 258 ps2_sendbyte(ps2dev, 0x38, FSP_CMD_TIMEOUT2); 259 ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); 260 261 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) 262 return -1; 263 264 if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) { 265 ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2); 266 } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) { 267 /* swapping is required */ 268 ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2); 269 } else { 270 /* swapping isn't necessary */ 271 ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2); 272 } 273 274 ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); 275 rc = 0; 276 277 out: 278 mutex_unlock(&ps2dev->cmd_mutex); 279 dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", 280 reg_val, rc); 281 return rc; 282 } 283 284 static int fsp_get_version(struct psmouse *psmouse, int *version) 285 { 286 if (fsp_reg_read(psmouse, FSP_REG_VERSION, version)) 287 return -EIO; 288 289 return 0; 290 } 291 292 static int fsp_get_revision(struct psmouse *psmouse, int *rev) 293 { 294 if (fsp_reg_read(psmouse, FSP_REG_REVISION, rev)) 295 return -EIO; 296 297 return 0; 298 } 299 300 static int fsp_get_buttons(struct psmouse *psmouse, int *btn) 301 { 302 static const int buttons[] = { 303 0x16, /* Left/Middle/Right/Forward/Backward & Scroll Up/Down */ 304 0x06, /* Left/Middle/Right & Scroll Up/Down/Right/Left */ 305 0x04, /* Left/Middle/Right & Scroll Up/Down */ 306 0x02, /* Left/Middle/Right */ 307 }; 308 int val; 309 310 if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS1, &val) == -1) 311 return -EIO; 312 313 *btn = buttons[(val & 0x30) >> 4]; 314 return 0; 315 } 316 317 /* Enable on-pad command tag output */ 318 static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable) 319 { 320 int v, nv; 321 int res = 0; 322 323 if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) { 324 dev_err(&psmouse->ps2dev.serio->dev, "Unable get OPC state.\n"); 325 return -EIO; 326 } 327 328 if (enable) 329 nv = v | FSP_BIT_EN_OPC_TAG; 330 else 331 nv = v & ~FSP_BIT_EN_OPC_TAG; 332 333 /* only write if necessary */ 334 if (nv != v) { 335 fsp_reg_write_enable(psmouse, true); 336 res = fsp_reg_write(psmouse, FSP_REG_OPC_QDOWN, nv); 337 fsp_reg_write_enable(psmouse, false); 338 } 339 340 if (res != 0) { 341 dev_err(&psmouse->ps2dev.serio->dev, 342 "Unable to enable OPC tag.\n"); 343 res = -EIO; 344 } 345 346 return res; 347 } 348 349 static int fsp_onpad_vscr(struct psmouse *psmouse, bool enable) 350 { 351 struct fsp_data *pad = psmouse->private; 352 int val; 353 354 if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val)) 355 return -EIO; 356 357 pad->vscroll = enable; 358 359 if (enable) 360 val |= (FSP_BIT_FIX_VSCR | FSP_BIT_ONPAD_ENABLE); 361 else 362 val &= ~FSP_BIT_FIX_VSCR; 363 364 if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val)) 365 return -EIO; 366 367 return 0; 368 } 369 370 static int fsp_onpad_hscr(struct psmouse *psmouse, bool enable) 371 { 372 struct fsp_data *pad = psmouse->private; 373 int val, v2; 374 375 if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val)) 376 return -EIO; 377 378 if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &v2)) 379 return -EIO; 380 381 pad->hscroll = enable; 382 383 if (enable) { 384 val |= (FSP_BIT_FIX_HSCR | FSP_BIT_ONPAD_ENABLE); 385 v2 |= FSP_BIT_EN_MSID6; 386 } else { 387 val &= ~FSP_BIT_FIX_HSCR; 388 v2 &= ~(FSP_BIT_EN_MSID6 | FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8); 389 } 390 391 if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val)) 392 return -EIO; 393 394 /* reconfigure horizontal scrolling packet output */ 395 if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, v2)) 396 return -EIO; 397 398 return 0; 399 } 400 401 /* 402 * Write device specific initial parameters. 403 * 404 * ex: 0xab 0xcd - write oxcd into register 0xab 405 */ 406 static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data, 407 const char *buf, size_t count) 408 { 409 unsigned long reg, val; 410 char *rest; 411 ssize_t retval; 412 413 reg = simple_strtoul(buf, &rest, 16); 414 if (rest == buf || *rest != ' ' || reg > 0xff) 415 return -EINVAL; 416 417 if (strict_strtoul(rest + 1, 16, &val) || val > 0xff) 418 return -EINVAL; 419 420 if (fsp_reg_write_enable(psmouse, true)) 421 return -EIO; 422 423 retval = fsp_reg_write(psmouse, reg, val) < 0 ? -EIO : count; 424 425 fsp_reg_write_enable(psmouse, false); 426 427 return count; 428 } 429 430 PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg); 431 432 static ssize_t fsp_attr_show_getreg(struct psmouse *psmouse, 433 void *data, char *buf) 434 { 435 struct fsp_data *pad = psmouse->private; 436 437 return sprintf(buf, "%02x%02x\n", pad->last_reg, pad->last_val); 438 } 439 440 /* 441 * Read a register from device. 442 * 443 * ex: 0xab -- read content from register 0xab 444 */ 445 static ssize_t fsp_attr_set_getreg(struct psmouse *psmouse, void *data, 446 const char *buf, size_t count) 447 { 448 struct fsp_data *pad = psmouse->private; 449 unsigned long reg; 450 int val; 451 452 if (strict_strtoul(buf, 16, ®) || reg > 0xff) 453 return -EINVAL; 454 455 if (fsp_reg_read(psmouse, reg, &val)) 456 return -EIO; 457 458 pad->last_reg = reg; 459 pad->last_val = val; 460 461 return count; 462 } 463 464 PSMOUSE_DEFINE_ATTR(getreg, S_IWUSR | S_IRUGO, NULL, 465 fsp_attr_show_getreg, fsp_attr_set_getreg); 466 467 static ssize_t fsp_attr_show_pagereg(struct psmouse *psmouse, 468 void *data, char *buf) 469 { 470 int val = 0; 471 472 if (fsp_page_reg_read(psmouse, &val)) 473 return -EIO; 474 475 return sprintf(buf, "%02x\n", val); 476 } 477 478 static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data, 479 const char *buf, size_t count) 480 { 481 unsigned long val; 482 483 if (strict_strtoul(buf, 16, &val) || val > 0xff) 484 return -EINVAL; 485 486 if (fsp_page_reg_write(psmouse, val)) 487 return -EIO; 488 489 return count; 490 } 491 492 PSMOUSE_DEFINE_ATTR(page, S_IWUSR | S_IRUGO, NULL, 493 fsp_attr_show_pagereg, fsp_attr_set_pagereg); 494 495 static ssize_t fsp_attr_show_vscroll(struct psmouse *psmouse, 496 void *data, char *buf) 497 { 498 struct fsp_data *pad = psmouse->private; 499 500 return sprintf(buf, "%d\n", pad->vscroll); 501 } 502 503 static ssize_t fsp_attr_set_vscroll(struct psmouse *psmouse, void *data, 504 const char *buf, size_t count) 505 { 506 unsigned long val; 507 508 if (strict_strtoul(buf, 10, &val) || val > 1) 509 return -EINVAL; 510 511 fsp_onpad_vscr(psmouse, val); 512 513 return count; 514 } 515 516 PSMOUSE_DEFINE_ATTR(vscroll, S_IWUSR | S_IRUGO, NULL, 517 fsp_attr_show_vscroll, fsp_attr_set_vscroll); 518 519 static ssize_t fsp_attr_show_hscroll(struct psmouse *psmouse, 520 void *data, char *buf) 521 { 522 struct fsp_data *pad = psmouse->private; 523 524 return sprintf(buf, "%d\n", pad->hscroll); 525 } 526 527 static ssize_t fsp_attr_set_hscroll(struct psmouse *psmouse, void *data, 528 const char *buf, size_t count) 529 { 530 unsigned long val; 531 532 if (strict_strtoul(buf, 10, &val) || val > 1) 533 return -EINVAL; 534 535 fsp_onpad_hscr(psmouse, val); 536 537 return count; 538 } 539 540 PSMOUSE_DEFINE_ATTR(hscroll, S_IWUSR | S_IRUGO, NULL, 541 fsp_attr_show_hscroll, fsp_attr_set_hscroll); 542 543 static ssize_t fsp_attr_show_flags(struct psmouse *psmouse, 544 void *data, char *buf) 545 { 546 struct fsp_data *pad = psmouse->private; 547 548 return sprintf(buf, "%c\n", 549 pad->flags & FSPDRV_FLAG_EN_OPC ? 'C' : 'c'); 550 } 551 552 static ssize_t fsp_attr_set_flags(struct psmouse *psmouse, void *data, 553 const char *buf, size_t count) 554 { 555 struct fsp_data *pad = psmouse->private; 556 size_t i; 557 558 for (i = 0; i < count; i++) { 559 switch (buf[i]) { 560 case 'C': 561 pad->flags |= FSPDRV_FLAG_EN_OPC; 562 break; 563 case 'c': 564 pad->flags &= ~FSPDRV_FLAG_EN_OPC; 565 break; 566 default: 567 return -EINVAL; 568 } 569 } 570 return count; 571 } 572 573 PSMOUSE_DEFINE_ATTR(flags, S_IWUSR | S_IRUGO, NULL, 574 fsp_attr_show_flags, fsp_attr_set_flags); 575 576 static ssize_t fsp_attr_show_ver(struct psmouse *psmouse, 577 void *data, char *buf) 578 { 579 return sprintf(buf, "Sentelic FSP kernel module %s\n", fsp_drv_ver); 580 } 581 582 PSMOUSE_DEFINE_RO_ATTR(ver, S_IRUGO, NULL, fsp_attr_show_ver); 583 584 static struct attribute *fsp_attributes[] = { 585 &psmouse_attr_setreg.dattr.attr, 586 &psmouse_attr_getreg.dattr.attr, 587 &psmouse_attr_page.dattr.attr, 588 &psmouse_attr_vscroll.dattr.attr, 589 &psmouse_attr_hscroll.dattr.attr, 590 &psmouse_attr_flags.dattr.attr, 591 &psmouse_attr_ver.dattr.attr, 592 NULL 593 }; 594 595 static struct attribute_group fsp_attribute_group = { 596 .attrs = fsp_attributes, 597 }; 598 599 #ifdef FSP_DEBUG 600 static void fsp_packet_debug(unsigned char packet[]) 601 { 602 static unsigned int ps2_packet_cnt; 603 static unsigned int ps2_last_second; 604 unsigned int jiffies_msec; 605 606 ps2_packet_cnt++; 607 jiffies_msec = jiffies_to_msecs(jiffies); 608 printk(KERN_DEBUG "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n", 609 jiffies_msec, packet[0], packet[1], packet[2], packet[3]); 610 611 if (jiffies_msec - ps2_last_second > 1000) { 612 printk(KERN_DEBUG "PS/2 packets/sec = %d\n", ps2_packet_cnt); 613 ps2_packet_cnt = 0; 614 ps2_last_second = jiffies_msec; 615 } 616 } 617 #else 618 static void fsp_packet_debug(unsigned char packet[]) 619 { 620 } 621 #endif 622 623 static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) 624 { 625 struct input_dev *dev = psmouse->dev; 626 struct fsp_data *ad = psmouse->private; 627 unsigned char *packet = psmouse->packet; 628 unsigned char button_status = 0, lscroll = 0, rscroll = 0; 629 int rel_x, rel_y; 630 631 if (psmouse->pktcnt < 4) 632 return PSMOUSE_GOOD_DATA; 633 634 /* 635 * Full packet accumulated, process it 636 */ 637 638 switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { 639 case FSP_PKT_TYPE_ABS: 640 dev_warn(&psmouse->ps2dev.serio->dev, 641 "Unexpected absolute mode packet, ignored.\n"); 642 break; 643 644 case FSP_PKT_TYPE_NORMAL_OPC: 645 /* on-pad click, filter it if necessary */ 646 if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC) 647 packet[0] &= ~BIT(0); 648 /* fall through */ 649 650 case FSP_PKT_TYPE_NORMAL: 651 /* normal packet */ 652 /* special packet data translation from on-pad packets */ 653 if (packet[3] != 0) { 654 if (packet[3] & BIT(0)) 655 button_status |= 0x01; /* wheel down */ 656 if (packet[3] & BIT(1)) 657 button_status |= 0x0f; /* wheel up */ 658 if (packet[3] & BIT(2)) 659 button_status |= BIT(5);/* horizontal left */ 660 if (packet[3] & BIT(3)) 661 button_status |= BIT(4);/* horizontal right */ 662 /* push back to packet queue */ 663 if (button_status != 0) 664 packet[3] = button_status; 665 rscroll = (packet[3] >> 4) & 1; 666 lscroll = (packet[3] >> 5) & 1; 667 } 668 /* 669 * Processing wheel up/down and extra button events 670 */ 671 input_report_rel(dev, REL_WHEEL, 672 (int)(packet[3] & 8) - (int)(packet[3] & 7)); 673 input_report_rel(dev, REL_HWHEEL, lscroll - rscroll); 674 input_report_key(dev, BTN_BACK, lscroll); 675 input_report_key(dev, BTN_FORWARD, rscroll); 676 677 /* 678 * Standard PS/2 Mouse 679 */ 680 input_report_key(dev, BTN_LEFT, packet[0] & 1); 681 input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1); 682 input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1); 683 684 rel_x = packet[1] ? (int)packet[1] - (int)((packet[0] << 4) & 0x100) : 0; 685 rel_y = packet[2] ? (int)((packet[0] << 3) & 0x100) - (int)packet[2] : 0; 686 687 input_report_rel(dev, REL_X, rel_x); 688 input_report_rel(dev, REL_Y, rel_y); 689 break; 690 } 691 692 input_sync(dev); 693 694 fsp_packet_debug(packet); 695 696 return PSMOUSE_FULL_PACKET; 697 } 698 699 static int fsp_activate_protocol(struct psmouse *psmouse) 700 { 701 struct fsp_data *pad = psmouse->private; 702 struct ps2dev *ps2dev = &psmouse->ps2dev; 703 unsigned char param[2]; 704 int val; 705 706 /* 707 * Standard procedure to enter FSP Intellimouse mode 708 * (scrolling wheel, 4th and 5th buttons) 709 */ 710 param[0] = 200; 711 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); 712 param[0] = 200; 713 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); 714 param[0] = 80; 715 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); 716 717 ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); 718 if (param[0] != 0x04) { 719 dev_err(&psmouse->ps2dev.serio->dev, 720 "Unable to enable 4 bytes packet format.\n"); 721 return -EIO; 722 } 723 724 if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) { 725 dev_err(&psmouse->ps2dev.serio->dev, 726 "Unable to read SYSCTL5 register.\n"); 727 return -EIO; 728 } 729 730 val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8); 731 /* Ensure we are not in absolute mode */ 732 val &= ~FSP_BIT_EN_PKT_G0; 733 if (pad->buttons == 0x06) { 734 /* Left/Middle/Right & Scroll Up/Down/Right/Left */ 735 val |= FSP_BIT_EN_MSID6; 736 } 737 738 if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) { 739 dev_err(&psmouse->ps2dev.serio->dev, 740 "Unable to set up required mode bits.\n"); 741 return -EIO; 742 } 743 744 /* 745 * Enable OPC tags such that driver can tell the difference between 746 * on-pad and real button click 747 */ 748 if (fsp_opc_tag_enable(psmouse, true)) 749 dev_warn(&psmouse->ps2dev.serio->dev, 750 "Failed to enable OPC tag mode.\n"); 751 752 /* Enable on-pad vertical and horizontal scrolling */ 753 fsp_onpad_vscr(psmouse, true); 754 fsp_onpad_hscr(psmouse, true); 755 756 return 0; 757 } 758 759 int fsp_detect(struct psmouse *psmouse, bool set_properties) 760 { 761 int id; 762 763 if (fsp_reg_read(psmouse, FSP_REG_DEVICE_ID, &id)) 764 return -EIO; 765 766 if (id != 0x01) 767 return -ENODEV; 768 769 if (set_properties) { 770 psmouse->vendor = "Sentelic"; 771 psmouse->name = "FingerSensingPad"; 772 } 773 774 return 0; 775 } 776 777 static void fsp_reset(struct psmouse *psmouse) 778 { 779 fsp_opc_tag_enable(psmouse, false); 780 fsp_onpad_vscr(psmouse, false); 781 fsp_onpad_hscr(psmouse, false); 782 } 783 784 static void fsp_disconnect(struct psmouse *psmouse) 785 { 786 sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, 787 &fsp_attribute_group); 788 789 fsp_reset(psmouse); 790 kfree(psmouse->private); 791 } 792 793 static int fsp_reconnect(struct psmouse *psmouse) 794 { 795 int version; 796 797 if (fsp_detect(psmouse, 0)) 798 return -ENODEV; 799 800 if (fsp_get_version(psmouse, &version)) 801 return -ENODEV; 802 803 if (fsp_activate_protocol(psmouse)) 804 return -EIO; 805 806 return 0; 807 } 808 809 int fsp_init(struct psmouse *psmouse) 810 { 811 struct fsp_data *priv; 812 int ver, rev, buttons; 813 int error; 814 815 if (fsp_get_version(psmouse, &ver) || 816 fsp_get_revision(psmouse, &rev) || 817 fsp_get_buttons(psmouse, &buttons)) { 818 return -ENODEV; 819 } 820 821 printk(KERN_INFO 822 "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n", 823 ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7); 824 825 psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); 826 if (!priv) 827 return -ENOMEM; 828 829 priv->ver = ver; 830 priv->rev = rev; 831 priv->buttons = buttons; 832 833 /* enable on-pad click by default */ 834 priv->flags |= FSPDRV_FLAG_EN_OPC; 835 836 /* Set up various supported input event bits */ 837 __set_bit(BTN_BACK, psmouse->dev->keybit); 838 __set_bit(BTN_FORWARD, psmouse->dev->keybit); 839 __set_bit(REL_WHEEL, psmouse->dev->relbit); 840 __set_bit(REL_HWHEEL, psmouse->dev->relbit); 841 842 psmouse->protocol_handler = fsp_process_byte; 843 psmouse->disconnect = fsp_disconnect; 844 psmouse->reconnect = fsp_reconnect; 845 psmouse->cleanup = fsp_reset; 846 psmouse->pktsize = 4; 847 848 /* set default packet output based on number of buttons we found */ 849 error = fsp_activate_protocol(psmouse); 850 if (error) 851 goto err_out; 852 853 error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, 854 &fsp_attribute_group); 855 if (error) { 856 dev_err(&psmouse->ps2dev.serio->dev, 857 "Failed to create sysfs attributes (%d)", error); 858 goto err_out; 859 } 860 861 return 0; 862 863 err_out: 864 kfree(psmouse->private); 865 psmouse->private = NULL; 866 return error; 867 } 868