Linux Audio

Check our new training course

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