1 // SPDX-License-Identifier: GPL-2.0-only
3 * Cypress Trackpad PS/2 mouse driver
5 * Copyright (c) 2012 Cypress Semiconductor Corporation.
8 * Dudley Du <dudl@cypress.com>
10 * Additional contributors include:
11 * Kamal Mostafa <kamal@canonical.com>
12 * Kyle Fazzari <git@status.e4ward.com>
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/slab.h>
18 #include <linux/serio.h>
19 #include <linux/libps2.h>
20 #include <linux/input.h>
21 #include <linux/input/mt.h>
22 #include <linux/sched.h>
23 #include <linux/wait.h>
25 #include "cypress_ps2.h"
27 #undef CYTP_DEBUG_VERBOSE /* define this and DEBUG for more verbose dump */
29 static void cypress_set_packet_size(struct psmouse
*psmouse
, unsigned int n
)
31 struct cytp_data
*cytp
= psmouse
->private;
35 static const u8 cytp_rate
[] = {10, 20, 40, 60, 100, 200};
36 static const u8 cytp_resolution
[] = {0x00, 0x01, 0x02, 0x03};
38 static int cypress_ps2_sendbyte(struct psmouse
*psmouse
, u8 cmd
)
40 struct ps2dev
*ps2dev
= &psmouse
->ps2dev
;
43 error
= ps2_sendbyte(ps2dev
, cmd
, CYTP_CMD_TIMEOUT
);
46 "sending command 0x%02x failed, resp 0x%02x, error %d\n",
47 cmd
, ps2dev
->nak
, error
);
51 #ifdef CYTP_DEBUG_VERBOSE
52 psmouse_dbg(psmouse
, "sending command 0x%02x succeeded\n", cmd
);
58 static int cypress_ps2_ext_cmd(struct psmouse
*psmouse
, u8 prefix
, u8 nibble
)
60 struct ps2dev
*ps2dev
= &psmouse
->ps2dev
;
61 int tries
= CYTP_PS2_CMD_TRIES
;
64 ps2_begin_command(ps2dev
);
68 * Send extension command byte (0xE8 or 0xF3).
69 * If sending the command fails, send recovery command
70 * to make the device return to the ready state.
72 rc
= cypress_ps2_sendbyte(psmouse
, prefix
);
74 rc
= cypress_ps2_sendbyte(psmouse
, 0x00);
76 rc
= cypress_ps2_sendbyte(psmouse
, 0x0a);
80 rc
= cypress_ps2_sendbyte(psmouse
, nibble
);
82 rc
= cypress_ps2_sendbyte(psmouse
, nibble
);
87 } while (--tries
> 0);
89 ps2_end_command(ps2dev
);
94 static bool cypress_verify_cmd_state(struct psmouse
*psmouse
, u8 cmd
, u8
* param
)
96 bool rate_match
= false;
97 bool resolution_match
= false;
100 /* callers will do further checking. */
101 if (cmd
== CYTP_CMD_READ_CYPRESS_ID
||
102 cmd
== CYTP_CMD_STANDARD_MODE
||
103 cmd
== CYTP_CMD_READ_TP_METRICS
)
106 if ((~param
[0] & DFLT_RESP_BITS_VALID
) == DFLT_RESP_BITS_VALID
&&
107 (param
[0] & DFLT_RESP_BIT_MODE
) == DFLT_RESP_STREAM_MODE
) {
108 for (i
= 0; i
< sizeof(cytp_resolution
); i
++)
109 if (cytp_resolution
[i
] == param
[1])
110 resolution_match
= true;
112 for (i
= 0; i
< sizeof(cytp_rate
); i
++)
113 if (cytp_rate
[i
] == param
[2])
116 if (resolution_match
&& rate_match
)
120 psmouse_dbg(psmouse
, "verify cmd state failed.\n");
124 static int cypress_send_ext_cmd(struct psmouse
*psmouse
, u8 cmd
, u8
*param
)
126 u8 cmd_prefix
= PSMOUSE_CMD_SETRES
& 0xff;
127 unsigned int resp_size
= cmd
== CYTP_CMD_READ_TP_METRICS
? 8 : 3;
128 unsigned int ps2_cmd
= (PSMOUSE_CMD_GETINFO
& 0xff) | (resp_size
<< 8);
129 int tries
= CYTP_PS2_CMD_TRIES
;
132 psmouse_dbg(psmouse
, "send extension cmd 0x%02x, [%d %d %d %d]\n",
133 cmd
, DECODE_CMD_AA(cmd
), DECODE_CMD_BB(cmd
),
134 DECODE_CMD_CC(cmd
), DECODE_CMD_DD(cmd
));
137 cypress_ps2_ext_cmd(psmouse
, cmd_prefix
, DECODE_CMD_DD(cmd
));
138 cypress_ps2_ext_cmd(psmouse
, cmd_prefix
, DECODE_CMD_CC(cmd
));
139 cypress_ps2_ext_cmd(psmouse
, cmd_prefix
, DECODE_CMD_BB(cmd
));
140 cypress_ps2_ext_cmd(psmouse
, cmd_prefix
, DECODE_CMD_AA(cmd
));
142 error
= ps2_command(&psmouse
->ps2dev
, param
, ps2_cmd
);
144 psmouse_dbg(psmouse
, "Command 0x%02x failed: %d\n",
148 "Command 0x%02x response data (0x): %*ph\n",
149 cmd
, resp_size
, param
);
151 if (cypress_verify_cmd_state(psmouse
, cmd
, param
))
154 } while (--tries
> 0);
159 int cypress_detect(struct psmouse
*psmouse
, bool set_properties
)
163 if (cypress_send_ext_cmd(psmouse
, CYTP_CMD_READ_CYPRESS_ID
, param
))
166 /* Check for Cypress Trackpad signature bytes: 0x33 0xCC */
167 if (param
[0] != 0x33 || param
[1] != 0xCC)
170 if (set_properties
) {
171 psmouse
->vendor
= "Cypress";
172 psmouse
->name
= "Trackpad";
178 static int cypress_read_fw_version(struct psmouse
*psmouse
)
180 struct cytp_data
*cytp
= psmouse
->private;
183 if (cypress_send_ext_cmd(psmouse
, CYTP_CMD_READ_CYPRESS_ID
, param
))
186 /* Check for Cypress Trackpad signature bytes: 0x33 0xCC */
187 if (param
[0] != 0x33 || param
[1] != 0xCC)
190 cytp
->fw_version
= param
[2] & FW_VERSION_MASX
;
191 cytp
->tp_metrics_supported
= (param
[2] & TP_METRICS_MASK
) ? 1 : 0;
194 * Trackpad fw_version 11 (in Dell XPS12) yields a bogus response to
195 * CYTP_CMD_READ_TP_METRICS so do not try to use it. LP: #1103594.
197 if (cytp
->fw_version
>= 11)
198 cytp
->tp_metrics_supported
= 0;
200 psmouse_dbg(psmouse
, "cytp->fw_version = %d\n", cytp
->fw_version
);
201 psmouse_dbg(psmouse
, "cytp->tp_metrics_supported = %d\n",
202 cytp
->tp_metrics_supported
);
207 static int cypress_read_tp_metrics(struct psmouse
*psmouse
)
209 struct cytp_data
*cytp
= psmouse
->private;
212 /* set default values for tp metrics. */
213 cytp
->tp_width
= CYTP_DEFAULT_WIDTH
;
214 cytp
->tp_high
= CYTP_DEFAULT_HIGH
;
215 cytp
->tp_max_abs_x
= CYTP_ABS_MAX_X
;
216 cytp
->tp_max_abs_y
= CYTP_ABS_MAX_Y
;
217 cytp
->tp_min_pressure
= CYTP_MIN_PRESSURE
;
218 cytp
->tp_max_pressure
= CYTP_MAX_PRESSURE
;
219 cytp
->tp_res_x
= cytp
->tp_max_abs_x
/ cytp
->tp_width
;
220 cytp
->tp_res_y
= cytp
->tp_max_abs_y
/ cytp
->tp_high
;
222 if (!cytp
->tp_metrics_supported
)
225 memset(param
, 0, sizeof(param
));
226 if (cypress_send_ext_cmd(psmouse
, CYTP_CMD_READ_TP_METRICS
, param
) == 0) {
227 /* Update trackpad parameters. */
228 cytp
->tp_max_abs_x
= (param
[1] << 8) | param
[0];
229 cytp
->tp_max_abs_y
= (param
[3] << 8) | param
[2];
230 cytp
->tp_min_pressure
= param
[4];
231 cytp
->tp_max_pressure
= param
[5];
234 if (!cytp
->tp_max_pressure
||
235 cytp
->tp_max_pressure
< cytp
->tp_min_pressure
||
236 !cytp
->tp_width
|| !cytp
->tp_high
||
237 !cytp
->tp_max_abs_x
||
238 cytp
->tp_max_abs_x
< cytp
->tp_width
||
239 !cytp
->tp_max_abs_y
||
240 cytp
->tp_max_abs_y
< cytp
->tp_high
)
243 cytp
->tp_res_x
= cytp
->tp_max_abs_x
/ cytp
->tp_width
;
244 cytp
->tp_res_y
= cytp
->tp_max_abs_y
/ cytp
->tp_high
;
246 #ifdef CYTP_DEBUG_VERBOSE
247 psmouse_dbg(psmouse
, "Dump trackpad hardware configuration as below:\n");
248 psmouse_dbg(psmouse
, "cytp->tp_width = %d\n", cytp
->tp_width
);
249 psmouse_dbg(psmouse
, "cytp->tp_high = %d\n", cytp
->tp_high
);
250 psmouse_dbg(psmouse
, "cytp->tp_max_abs_x = %d\n", cytp
->tp_max_abs_x
);
251 psmouse_dbg(psmouse
, "cytp->tp_max_abs_y = %d\n", cytp
->tp_max_abs_y
);
252 psmouse_dbg(psmouse
, "cytp->tp_min_pressure = %d\n", cytp
->tp_min_pressure
);
253 psmouse_dbg(psmouse
, "cytp->tp_max_pressure = %d\n", cytp
->tp_max_pressure
);
254 psmouse_dbg(psmouse
, "cytp->tp_res_x = %d\n", cytp
->tp_res_x
);
255 psmouse_dbg(psmouse
, "cytp->tp_res_y = %d\n", cytp
->tp_res_y
);
257 psmouse_dbg(psmouse
, "tp_type_APA = %d\n",
258 (param
[6] & TP_METRICS_BIT_APA
) ? 1 : 0);
259 psmouse_dbg(psmouse
, "tp_type_MTG = %d\n",
260 (param
[6] & TP_METRICS_BIT_MTG
) ? 1 : 0);
261 psmouse_dbg(psmouse
, "tp_palm = %d\n",
262 (param
[6] & TP_METRICS_BIT_PALM
) ? 1 : 0);
263 psmouse_dbg(psmouse
, "tp_stubborn = %d\n",
264 (param
[6] & TP_METRICS_BIT_STUBBORN
) ? 1 : 0);
265 psmouse_dbg(psmouse
, "tp_1f_jitter = %d\n",
266 (param
[6] & TP_METRICS_BIT_1F_JITTER
) >> 2);
267 psmouse_dbg(psmouse
, "tp_2f_jitter = %d\n",
268 (param
[6] & TP_METRICS_BIT_2F_JITTER
) >> 4);
269 psmouse_dbg(psmouse
, "tp_1f_spike = %d\n",
270 param
[7] & TP_METRICS_BIT_1F_SPIKE
);
271 psmouse_dbg(psmouse
, "tp_2f_spike = %d\n",
272 (param
[7] & TP_METRICS_BIT_2F_SPIKE
) >> 2);
273 psmouse_dbg(psmouse
, "tp_abs_packet_format_set = %d\n",
274 (param
[7] & TP_METRICS_BIT_ABS_PKT_FORMAT_SET
) >> 4);
280 static int cypress_query_hardware(struct psmouse
*psmouse
)
284 error
= cypress_read_fw_version(psmouse
);
288 error
= cypress_read_tp_metrics(psmouse
);
295 static int cypress_set_absolute_mode(struct psmouse
*psmouse
)
297 struct cytp_data
*cytp
= psmouse
->private;
301 error
= cypress_send_ext_cmd(psmouse
, CYTP_CMD_ABS_WITH_PRESSURE_MODE
,
306 cytp
->mode
= (cytp
->mode
& ~CYTP_BIT_ABS_REL_MASK
)
307 | CYTP_BIT_ABS_PRESSURE
;
308 cypress_set_packet_size(psmouse
, 5);
314 * Reset trackpad device.
315 * This is also the default mode when trackpad powered on.
317 static void cypress_reset(struct psmouse
*psmouse
)
319 struct cytp_data
*cytp
= psmouse
->private;
323 psmouse_reset(psmouse
);
326 static int cypress_set_input_params(struct input_dev
*input
,
327 struct cytp_data
*cytp
)
331 if (!cytp
->tp_res_x
|| !cytp
->tp_res_y
)
334 __set_bit(EV_ABS
, input
->evbit
);
335 input_set_abs_params(input
, ABS_X
, 0, cytp
->tp_max_abs_x
, 0, 0);
336 input_set_abs_params(input
, ABS_Y
, 0, cytp
->tp_max_abs_y
, 0, 0);
337 input_set_abs_params(input
, ABS_PRESSURE
,
338 cytp
->tp_min_pressure
, cytp
->tp_max_pressure
, 0, 0);
339 input_set_abs_params(input
, ABS_TOOL_WIDTH
, 0, 255, 0, 0);
341 /* finger position */
342 input_set_abs_params(input
, ABS_MT_POSITION_X
, 0, cytp
->tp_max_abs_x
, 0, 0);
343 input_set_abs_params(input
, ABS_MT_POSITION_Y
, 0, cytp
->tp_max_abs_y
, 0, 0);
344 input_set_abs_params(input
, ABS_MT_PRESSURE
, 0, 255, 0, 0);
346 error
= input_mt_init_slots(input
, CYTP_MAX_MT_SLOTS
,
347 INPUT_MT_DROP_UNUSED
| INPUT_MT_TRACK
);
351 __set_bit(INPUT_PROP_SEMI_MT
, input
->propbit
);
353 input_abs_set_res(input
, ABS_X
, cytp
->tp_res_x
);
354 input_abs_set_res(input
, ABS_Y
, cytp
->tp_res_y
);
356 input_abs_set_res(input
, ABS_MT_POSITION_X
, cytp
->tp_res_x
);
357 input_abs_set_res(input
, ABS_MT_POSITION_Y
, cytp
->tp_res_y
);
359 __set_bit(BTN_TOUCH
, input
->keybit
);
360 __set_bit(BTN_TOOL_FINGER
, input
->keybit
);
361 __set_bit(BTN_TOOL_DOUBLETAP
, input
->keybit
);
362 __set_bit(BTN_TOOL_TRIPLETAP
, input
->keybit
);
363 __set_bit(BTN_TOOL_QUADTAP
, input
->keybit
);
364 __set_bit(BTN_TOOL_QUINTTAP
, input
->keybit
);
366 __clear_bit(EV_REL
, input
->evbit
);
367 __clear_bit(REL_X
, input
->relbit
);
368 __clear_bit(REL_Y
, input
->relbit
);
370 __set_bit(EV_KEY
, input
->evbit
);
371 __set_bit(BTN_LEFT
, input
->keybit
);
372 __set_bit(BTN_RIGHT
, input
->keybit
);
373 __set_bit(BTN_MIDDLE
, input
->keybit
);
378 static int cypress_get_finger_count(u8 header_byte
)
383 bits6_7
= header_byte
>> 6;
384 finger_count
= bits6_7
& 0x03;
386 if (finger_count
== 1)
389 if (header_byte
& ABS_HSCROLL_BIT
) {
390 /* HSCROLL gets added on to 0 finger count. */
391 switch (finger_count
) {
395 /* Invalid contact (e.g. palm). Ignore it. */
404 static int cypress_parse_packet(struct psmouse
*psmouse
,
405 struct cytp_data
*cytp
,
406 struct cytp_report_data
*report_data
)
408 u8
*packet
= psmouse
->packet
;
409 u8 header_byte
= packet
[0];
411 memset(report_data
, 0, sizeof(struct cytp_report_data
));
413 report_data
->contact_cnt
= cypress_get_finger_count(header_byte
);
414 report_data
->tap
= (header_byte
& ABS_MULTIFINGER_TAP
) ? 1 : 0;
416 if (report_data
->contact_cnt
== 1) {
417 report_data
->contacts
[0].x
=
418 ((packet
[1] & 0x70) << 4) | packet
[2];
419 report_data
->contacts
[0].y
=
420 ((packet
[1] & 0x07) << 8) | packet
[3];
421 if (cytp
->mode
& CYTP_BIT_ABS_PRESSURE
)
422 report_data
->contacts
[0].z
= packet
[4];
424 } else if (report_data
->contact_cnt
>= 2) {
425 report_data
->contacts
[0].x
=
426 ((packet
[1] & 0x70) << 4) | packet
[2];
427 report_data
->contacts
[0].y
=
428 ((packet
[1] & 0x07) << 8) | packet
[3];
429 if (cytp
->mode
& CYTP_BIT_ABS_PRESSURE
)
430 report_data
->contacts
[0].z
= packet
[4];
432 report_data
->contacts
[1].x
=
433 ((packet
[5] & 0xf0) << 4) | packet
[6];
434 report_data
->contacts
[1].y
=
435 ((packet
[5] & 0x0f) << 8) | packet
[7];
436 if (cytp
->mode
& CYTP_BIT_ABS_PRESSURE
)
437 report_data
->contacts
[1].z
= report_data
->contacts
[0].z
;
440 report_data
->left
= (header_byte
& BTN_LEFT_BIT
) ? 1 : 0;
441 report_data
->right
= (header_byte
& BTN_RIGHT_BIT
) ? 1 : 0;
444 * This is only true if one of the mouse buttons were tapped. Make
445 * sure it doesn't turn into a click. The regular tap-to-click
446 * functionality will handle that on its own. If we don't do this,
447 * disabling tap-to-click won't affect the mouse button zones.
449 if (report_data
->tap
)
450 report_data
->left
= 0;
452 #ifdef CYTP_DEBUG_VERBOSE
455 int n
= report_data
->contact_cnt
;
456 psmouse_dbg(psmouse
, "Dump parsed report data as below:\n");
457 psmouse_dbg(psmouse
, "contact_cnt = %d\n",
458 report_data
->contact_cnt
);
459 if (n
> CYTP_MAX_MT_SLOTS
)
460 n
= CYTP_MAX_MT_SLOTS
;
461 for (i
= 0; i
< n
; i
++)
462 psmouse_dbg(psmouse
, "contacts[%d] = {%d, %d, %d}\n", i
,
463 report_data
->contacts
[i
].x
,
464 report_data
->contacts
[i
].y
,
465 report_data
->contacts
[i
].z
);
466 psmouse_dbg(psmouse
, "left = %d\n", report_data
->left
);
467 psmouse_dbg(psmouse
, "right = %d\n", report_data
->right
);
468 psmouse_dbg(psmouse
, "middle = %d\n", report_data
->middle
);
475 static void cypress_process_packet(struct psmouse
*psmouse
, bool zero_pkt
)
478 struct input_dev
*input
= psmouse
->dev
;
479 struct cytp_data
*cytp
= psmouse
->private;
480 struct cytp_report_data report_data
;
481 struct cytp_contact
*contact
;
482 struct input_mt_pos pos
[CYTP_MAX_MT_SLOTS
];
483 int slots
[CYTP_MAX_MT_SLOTS
];
486 cypress_parse_packet(psmouse
, cytp
, &report_data
);
488 n
= report_data
.contact_cnt
;
489 if (n
> CYTP_MAX_MT_SLOTS
)
490 n
= CYTP_MAX_MT_SLOTS
;
492 for (i
= 0; i
< n
; i
++) {
493 contact
= &report_data
.contacts
[i
];
494 pos
[i
].x
= contact
->x
;
495 pos
[i
].y
= contact
->y
;
498 input_mt_assign_slots(input
, slots
, pos
, n
, 0);
500 for (i
= 0; i
< n
; i
++) {
501 contact
= &report_data
.contacts
[i
];
502 input_mt_slot(input
, slots
[i
]);
503 input_mt_report_slot_state(input
, MT_TOOL_FINGER
, true);
504 input_report_abs(input
, ABS_MT_POSITION_X
, contact
->x
);
505 input_report_abs(input
, ABS_MT_POSITION_Y
, contact
->y
);
506 input_report_abs(input
, ABS_MT_PRESSURE
, contact
->z
);
509 input_mt_sync_frame(input
);
511 input_mt_report_finger_count(input
, report_data
.contact_cnt
);
513 input_report_key(input
, BTN_LEFT
, report_data
.left
);
514 input_report_key(input
, BTN_RIGHT
, report_data
.right
);
515 input_report_key(input
, BTN_MIDDLE
, report_data
.middle
);
520 static psmouse_ret_t
cypress_validate_byte(struct psmouse
*psmouse
)
523 int index
= psmouse
->pktcnt
- 1;
524 u8
*packet
= psmouse
->packet
;
525 struct cytp_data
*cytp
= psmouse
->private;
527 if (index
< 0 || index
> cytp
->pkt_size
)
528 return PSMOUSE_BAD_DATA
;
530 if (index
== 0 && (packet
[0] & 0xfc) == 0) {
531 /* call packet process for reporting finger leave. */
532 cypress_process_packet(psmouse
, 1);
533 return PSMOUSE_FULL_PACKET
;
537 * Perform validation (and adjust packet size) based only on the
538 * first byte; allow all further bytes through.
541 return PSMOUSE_GOOD_DATA
;
544 * If absolute/relative mode bit has not been set yet, just pass
547 if ((cytp
->mode
& CYTP_BIT_ABS_REL_MASK
) == 0)
548 return PSMOUSE_GOOD_DATA
;
550 if ((packet
[0] & 0x08) == 0x08)
551 return PSMOUSE_BAD_DATA
;
553 contact_cnt
= cypress_get_finger_count(packet
[0]);
554 if (cytp
->mode
& CYTP_BIT_ABS_NO_PRESSURE
)
555 cypress_set_packet_size(psmouse
, contact_cnt
== 2 ? 7 : 4);
557 cypress_set_packet_size(psmouse
, contact_cnt
== 2 ? 8 : 5);
559 return PSMOUSE_GOOD_DATA
;
562 static psmouse_ret_t
cypress_protocol_handler(struct psmouse
*psmouse
)
564 struct cytp_data
*cytp
= psmouse
->private;
566 if (psmouse
->pktcnt
>= cytp
->pkt_size
) {
567 cypress_process_packet(psmouse
, 0);
568 return PSMOUSE_FULL_PACKET
;
571 return cypress_validate_byte(psmouse
);
574 static void cypress_set_rate(struct psmouse
*psmouse
, unsigned int rate
)
576 struct cytp_data
*cytp
= psmouse
->private;
581 cytp
->mode
|= CYTP_BIT_HIGH_RATE
;
584 cytp
->mode
&= ~CYTP_BIT_HIGH_RATE
;
587 rate_param
= (u8
)rate
;
588 ps2_command(&psmouse
->ps2dev
, &rate_param
, PSMOUSE_CMD_SETRATE
);
591 static void cypress_disconnect(struct psmouse
*psmouse
)
593 cypress_reset(psmouse
);
594 kfree(psmouse
->private);
595 psmouse
->private = NULL
;
598 static int cypress_reconnect(struct psmouse
*psmouse
)
600 int tries
= CYTP_PS2_CMD_TRIES
;
604 cypress_reset(psmouse
);
605 error
= cypress_detect(psmouse
, false);
606 } while (error
&& (--tries
> 0));
609 psmouse_err(psmouse
, "Reconnect: unable to detect trackpad.\n");
613 error
= cypress_set_absolute_mode(psmouse
);
615 psmouse_err(psmouse
, "Reconnect: Unable to initialize Cypress absolute mode.\n");
622 int cypress_init(struct psmouse
*psmouse
)
624 struct cytp_data
*cytp
;
627 cytp
= kzalloc(sizeof(*cytp
), GFP_KERNEL
);
631 psmouse
->private = cytp
;
632 psmouse
->pktsize
= 8;
634 cypress_reset(psmouse
);
636 error
= cypress_query_hardware(psmouse
);
638 psmouse_err(psmouse
, "Unable to query Trackpad hardware.\n");
642 error
= cypress_set_absolute_mode(psmouse
);
644 psmouse_err(psmouse
, "init: Unable to initialize Cypress absolute mode.\n");
648 error
= cypress_set_input_params(psmouse
->dev
, cytp
);
650 psmouse_err(psmouse
, "init: Unable to set input params.\n");
655 psmouse
->protocol_handler
= cypress_protocol_handler
;
656 psmouse
->set_rate
= cypress_set_rate
;
657 psmouse
->disconnect
= cypress_disconnect
;
658 psmouse
->reconnect
= cypress_reconnect
;
659 psmouse
->cleanup
= cypress_reset
;
660 psmouse
->resync_time
= 0;
666 * Reset Cypress Trackpad as a standard mouse. Then
667 * let psmouse driver communicating with it as default PS2 mouse.
669 cypress_reset(psmouse
);
671 psmouse
->private = NULL
;