xref: /OK3568_Linux_fs/kernel/drivers/input/serio/libps2.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * PS/2 driver library
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 1999-2002 Vojtech Pavlik
6*4882a593Smuzhiyun  * Copyright (c) 2004 Dmitry Torokhov
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/delay.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/sched.h>
13*4882a593Smuzhiyun #include <linux/interrupt.h>
14*4882a593Smuzhiyun #include <linux/input.h>
15*4882a593Smuzhiyun #include <linux/serio.h>
16*4882a593Smuzhiyun #include <linux/i8042.h>
17*4882a593Smuzhiyun #include <linux/libps2.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define DRIVER_DESC	"PS/2 driver library"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
22*4882a593Smuzhiyun MODULE_DESCRIPTION("PS/2 driver library");
23*4882a593Smuzhiyun MODULE_LICENSE("GPL");
24*4882a593Smuzhiyun 
ps2_do_sendbyte(struct ps2dev * ps2dev,u8 byte,unsigned int timeout,unsigned int max_attempts)25*4882a593Smuzhiyun static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte,
26*4882a593Smuzhiyun 			   unsigned int timeout, unsigned int max_attempts)
27*4882a593Smuzhiyun 	__releases(&ps2dev->serio->lock) __acquires(&ps2dev->serio->lock)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	int attempt = 0;
30*4882a593Smuzhiyun 	int error;
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun 	lockdep_assert_held(&ps2dev->serio->lock);
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	do {
35*4882a593Smuzhiyun 		ps2dev->nak = 1;
36*4882a593Smuzhiyun 		ps2dev->flags |= PS2_FLAG_ACK;
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 		serio_continue_rx(ps2dev->serio);
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 		error = serio_write(ps2dev->serio, byte);
41*4882a593Smuzhiyun 		if (error)
42*4882a593Smuzhiyun 			dev_dbg(&ps2dev->serio->dev,
43*4882a593Smuzhiyun 				"failed to write %#02x: %d\n", byte, error);
44*4882a593Smuzhiyun 		else
45*4882a593Smuzhiyun 			wait_event_timeout(ps2dev->wait,
46*4882a593Smuzhiyun 					   !(ps2dev->flags & PS2_FLAG_ACK),
47*4882a593Smuzhiyun 					   msecs_to_jiffies(timeout));
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 		serio_pause_rx(ps2dev->serio);
50*4882a593Smuzhiyun 	} while (ps2dev->nak == PS2_RET_NAK && ++attempt < max_attempts);
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	ps2dev->flags &= ~PS2_FLAG_ACK;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	if (!error) {
55*4882a593Smuzhiyun 		switch (ps2dev->nak) {
56*4882a593Smuzhiyun 		case 0:
57*4882a593Smuzhiyun 			break;
58*4882a593Smuzhiyun 		case PS2_RET_NAK:
59*4882a593Smuzhiyun 			error = -EAGAIN;
60*4882a593Smuzhiyun 			break;
61*4882a593Smuzhiyun 		case PS2_RET_ERR:
62*4882a593Smuzhiyun 			error = -EPROTO;
63*4882a593Smuzhiyun 			break;
64*4882a593Smuzhiyun 		default:
65*4882a593Smuzhiyun 			error = -EIO;
66*4882a593Smuzhiyun 			break;
67*4882a593Smuzhiyun 		}
68*4882a593Smuzhiyun 	}
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	if (error || attempt > 1)
71*4882a593Smuzhiyun 		dev_dbg(&ps2dev->serio->dev,
72*4882a593Smuzhiyun 			"%02x - %d (%x), attempt %d\n",
73*4882a593Smuzhiyun 			byte, error, ps2dev->nak, attempt);
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	return error;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /*
79*4882a593Smuzhiyun  * ps2_sendbyte() sends a byte to the device and waits for acknowledge.
80*4882a593Smuzhiyun  * It doesn't handle retransmission, the caller is expected to handle
81*4882a593Smuzhiyun  * it when needed.
82*4882a593Smuzhiyun  *
83*4882a593Smuzhiyun  * ps2_sendbyte() can only be called from a process context.
84*4882a593Smuzhiyun  */
85*4882a593Smuzhiyun 
ps2_sendbyte(struct ps2dev * ps2dev,u8 byte,unsigned int timeout)86*4882a593Smuzhiyun int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	int retval;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	serio_pause_rx(ps2dev->serio);
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	retval = ps2_do_sendbyte(ps2dev, byte, timeout, 1);
93*4882a593Smuzhiyun 	dev_dbg(&ps2dev->serio->dev, "%02x - %x\n", byte, ps2dev->nak);
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	serio_continue_rx(ps2dev->serio);
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	return retval;
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun EXPORT_SYMBOL(ps2_sendbyte);
100*4882a593Smuzhiyun 
ps2_begin_command(struct ps2dev * ps2dev)101*4882a593Smuzhiyun void ps2_begin_command(struct ps2dev *ps2dev)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	mutex_lock(m);
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun EXPORT_SYMBOL(ps2_begin_command);
108*4882a593Smuzhiyun 
ps2_end_command(struct ps2dev * ps2dev)109*4882a593Smuzhiyun void ps2_end_command(struct ps2dev *ps2dev)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	mutex_unlock(m);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun EXPORT_SYMBOL(ps2_end_command);
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun /*
118*4882a593Smuzhiyun  * ps2_drain() waits for device to transmit requested number of bytes
119*4882a593Smuzhiyun  * and discards them.
120*4882a593Smuzhiyun  */
121*4882a593Smuzhiyun 
ps2_drain(struct ps2dev * ps2dev,size_t maxbytes,unsigned int timeout)122*4882a593Smuzhiyun void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	if (maxbytes > sizeof(ps2dev->cmdbuf)) {
125*4882a593Smuzhiyun 		WARN_ON(1);
126*4882a593Smuzhiyun 		maxbytes = sizeof(ps2dev->cmdbuf);
127*4882a593Smuzhiyun 	}
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	ps2_begin_command(ps2dev);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	serio_pause_rx(ps2dev->serio);
132*4882a593Smuzhiyun 	ps2dev->flags = PS2_FLAG_CMD;
133*4882a593Smuzhiyun 	ps2dev->cmdcnt = maxbytes;
134*4882a593Smuzhiyun 	serio_continue_rx(ps2dev->serio);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	wait_event_timeout(ps2dev->wait,
137*4882a593Smuzhiyun 			   !(ps2dev->flags & PS2_FLAG_CMD),
138*4882a593Smuzhiyun 			   msecs_to_jiffies(timeout));
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	ps2_end_command(ps2dev);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun EXPORT_SYMBOL(ps2_drain);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun /*
145*4882a593Smuzhiyun  * ps2_is_keyboard_id() checks received ID byte against the list of
146*4882a593Smuzhiyun  * known keyboard IDs.
147*4882a593Smuzhiyun  */
148*4882a593Smuzhiyun 
ps2_is_keyboard_id(u8 id_byte)149*4882a593Smuzhiyun bool ps2_is_keyboard_id(u8 id_byte)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	static const u8 keyboard_ids[] = {
152*4882a593Smuzhiyun 		0xab,	/* Regular keyboards		*/
153*4882a593Smuzhiyun 		0xac,	/* NCD Sun keyboard		*/
154*4882a593Smuzhiyun 		0x2b,	/* Trust keyboard, translated	*/
155*4882a593Smuzhiyun 		0x5d,	/* Trust keyboard		*/
156*4882a593Smuzhiyun 		0x60,	/* NMB SGI keyboard, translated */
157*4882a593Smuzhiyun 		0x47,	/* NMB SGI keyboard		*/
158*4882a593Smuzhiyun 	};
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	return memchr(keyboard_ids, id_byte, sizeof(keyboard_ids)) != NULL;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun EXPORT_SYMBOL(ps2_is_keyboard_id);
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun /*
165*4882a593Smuzhiyun  * ps2_adjust_timeout() is called after receiving 1st byte of command
166*4882a593Smuzhiyun  * response and tries to reduce remaining timeout to speed up command
167*4882a593Smuzhiyun  * completion.
168*4882a593Smuzhiyun  */
169*4882a593Smuzhiyun 
ps2_adjust_timeout(struct ps2dev * ps2dev,unsigned int command,unsigned int timeout)170*4882a593Smuzhiyun static int ps2_adjust_timeout(struct ps2dev *ps2dev,
171*4882a593Smuzhiyun 			      unsigned int command, unsigned int timeout)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	switch (command) {
174*4882a593Smuzhiyun 	case PS2_CMD_RESET_BAT:
175*4882a593Smuzhiyun 		/*
176*4882a593Smuzhiyun 		 * Device has sent the first response byte after
177*4882a593Smuzhiyun 		 * reset command, reset is thus done, so we can
178*4882a593Smuzhiyun 		 * shorten the timeout.
179*4882a593Smuzhiyun 		 * The next byte will come soon (keyboard) or not
180*4882a593Smuzhiyun 		 * at all (mouse).
181*4882a593Smuzhiyun 		 */
182*4882a593Smuzhiyun 		if (timeout > msecs_to_jiffies(100))
183*4882a593Smuzhiyun 			timeout = msecs_to_jiffies(100);
184*4882a593Smuzhiyun 		break;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	case PS2_CMD_GETID:
187*4882a593Smuzhiyun 		/*
188*4882a593Smuzhiyun 		 * Microsoft Natural Elite keyboard responds to
189*4882a593Smuzhiyun 		 * the GET ID command as it were a mouse, with
190*4882a593Smuzhiyun 		 * a single byte. Fail the command so atkbd will
191*4882a593Smuzhiyun 		 * use alternative probe to detect it.
192*4882a593Smuzhiyun 		 */
193*4882a593Smuzhiyun 		if (ps2dev->cmdbuf[1] == 0xaa) {
194*4882a593Smuzhiyun 			serio_pause_rx(ps2dev->serio);
195*4882a593Smuzhiyun 			ps2dev->flags = 0;
196*4882a593Smuzhiyun 			serio_continue_rx(ps2dev->serio);
197*4882a593Smuzhiyun 			timeout = 0;
198*4882a593Smuzhiyun 		}
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 		/*
201*4882a593Smuzhiyun 		 * If device behind the port is not a keyboard there
202*4882a593Smuzhiyun 		 * won't be 2nd byte of ID response.
203*4882a593Smuzhiyun 		 */
204*4882a593Smuzhiyun 		if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) {
205*4882a593Smuzhiyun 			serio_pause_rx(ps2dev->serio);
206*4882a593Smuzhiyun 			ps2dev->flags = ps2dev->cmdcnt = 0;
207*4882a593Smuzhiyun 			serio_continue_rx(ps2dev->serio);
208*4882a593Smuzhiyun 			timeout = 0;
209*4882a593Smuzhiyun 		}
210*4882a593Smuzhiyun 		break;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	default:
213*4882a593Smuzhiyun 		break;
214*4882a593Smuzhiyun 	}
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	return timeout;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun /*
220*4882a593Smuzhiyun  * ps2_command() sends a command and its parameters to the mouse,
221*4882a593Smuzhiyun  * then waits for the response and puts it in the param array.
222*4882a593Smuzhiyun  *
223*4882a593Smuzhiyun  * ps2_command() can only be called from a process context
224*4882a593Smuzhiyun  */
225*4882a593Smuzhiyun 
__ps2_command(struct ps2dev * ps2dev,u8 * param,unsigned int command)226*4882a593Smuzhiyun int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun 	unsigned int timeout;
229*4882a593Smuzhiyun 	unsigned int send = (command >> 12) & 0xf;
230*4882a593Smuzhiyun 	unsigned int receive = (command >> 8) & 0xf;
231*4882a593Smuzhiyun 	int rc;
232*4882a593Smuzhiyun 	int i;
233*4882a593Smuzhiyun 	u8 send_param[16];
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	if (receive > sizeof(ps2dev->cmdbuf)) {
236*4882a593Smuzhiyun 		WARN_ON(1);
237*4882a593Smuzhiyun 		return -EINVAL;
238*4882a593Smuzhiyun 	}
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	if (send && !param) {
241*4882a593Smuzhiyun 		WARN_ON(1);
242*4882a593Smuzhiyun 		return -EINVAL;
243*4882a593Smuzhiyun 	}
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	memcpy(send_param, param, send);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	serio_pause_rx(ps2dev->serio);
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
250*4882a593Smuzhiyun 	ps2dev->cmdcnt = receive;
251*4882a593Smuzhiyun 	if (receive && param)
252*4882a593Smuzhiyun 		for (i = 0; i < receive; i++)
253*4882a593Smuzhiyun 			ps2dev->cmdbuf[(receive - 1) - i] = param[i];
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	/* Signal that we are sending the command byte */
256*4882a593Smuzhiyun 	ps2dev->flags |= PS2_FLAG_ACK_CMD;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	/*
259*4882a593Smuzhiyun 	 * Some devices (Synaptics) peform the reset before
260*4882a593Smuzhiyun 	 * ACKing the reset command, and so it can take a long
261*4882a593Smuzhiyun 	 * time before the ACK arrives.
262*4882a593Smuzhiyun 	 */
263*4882a593Smuzhiyun 	timeout = command == PS2_CMD_RESET_BAT ? 1000 : 200;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	rc = ps2_do_sendbyte(ps2dev, command & 0xff, timeout, 2);
266*4882a593Smuzhiyun 	if (rc)
267*4882a593Smuzhiyun 		goto out_reset_flags;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	/* Now we are sending command parameters, if any */
270*4882a593Smuzhiyun 	ps2dev->flags &= ~PS2_FLAG_ACK_CMD;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	for (i = 0; i < send; i++) {
273*4882a593Smuzhiyun 		rc = ps2_do_sendbyte(ps2dev, param[i], 200, 2);
274*4882a593Smuzhiyun 		if (rc)
275*4882a593Smuzhiyun 			goto out_reset_flags;
276*4882a593Smuzhiyun 	}
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	serio_continue_rx(ps2dev->serio);
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	/*
281*4882a593Smuzhiyun 	 * The reset command takes a long time to execute.
282*4882a593Smuzhiyun 	 */
283*4882a593Smuzhiyun 	timeout = msecs_to_jiffies(command == PS2_CMD_RESET_BAT ? 4000 : 500);
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	timeout = wait_event_timeout(ps2dev->wait,
286*4882a593Smuzhiyun 				     !(ps2dev->flags & PS2_FLAG_CMD1), timeout);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	if (ps2dev->cmdcnt && !(ps2dev->flags & PS2_FLAG_CMD1)) {
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 		timeout = ps2_adjust_timeout(ps2dev, command, timeout);
291*4882a593Smuzhiyun 		wait_event_timeout(ps2dev->wait,
292*4882a593Smuzhiyun 				   !(ps2dev->flags & PS2_FLAG_CMD), timeout);
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	serio_pause_rx(ps2dev->serio);
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	if (param)
298*4882a593Smuzhiyun 		for (i = 0; i < receive; i++)
299*4882a593Smuzhiyun 			param[i] = ps2dev->cmdbuf[(receive - 1) - i];
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	if (ps2dev->cmdcnt &&
302*4882a593Smuzhiyun 	    (command != PS2_CMD_RESET_BAT || ps2dev->cmdcnt != 1)) {
303*4882a593Smuzhiyun 		rc = -EPROTO;
304*4882a593Smuzhiyun 		goto out_reset_flags;
305*4882a593Smuzhiyun 	}
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	rc = 0;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun  out_reset_flags:
310*4882a593Smuzhiyun 	ps2dev->flags = 0;
311*4882a593Smuzhiyun 	serio_continue_rx(ps2dev->serio);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	dev_dbg(&ps2dev->serio->dev,
314*4882a593Smuzhiyun 		"%02x [%*ph] - %x/%08lx [%*ph]\n",
315*4882a593Smuzhiyun 		command & 0xff, send, send_param,
316*4882a593Smuzhiyun 		ps2dev->nak, ps2dev->flags,
317*4882a593Smuzhiyun 		receive, param ?: send_param);
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	/*
320*4882a593Smuzhiyun 	 * ps_command() handles resends itself, so do not leak -EAGAIN
321*4882a593Smuzhiyun 	 * to the callers.
322*4882a593Smuzhiyun 	 */
323*4882a593Smuzhiyun 	return rc != -EAGAIN ? rc : -EPROTO;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun EXPORT_SYMBOL(__ps2_command);
326*4882a593Smuzhiyun 
ps2_command(struct ps2dev * ps2dev,u8 * param,unsigned int command)327*4882a593Smuzhiyun int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun 	int rc;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	ps2_begin_command(ps2dev);
332*4882a593Smuzhiyun 	rc = __ps2_command(ps2dev, param, command);
333*4882a593Smuzhiyun 	ps2_end_command(ps2dev);
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	return rc;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun EXPORT_SYMBOL(ps2_command);
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun /*
340*4882a593Smuzhiyun  * ps2_sliced_command() sends an extended PS/2 command to the mouse
341*4882a593Smuzhiyun  * using sliced syntax, understood by advanced devices, such as Logitech
342*4882a593Smuzhiyun  * or Synaptics touchpads. The command is encoded as:
343*4882a593Smuzhiyun  * 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu
344*4882a593Smuzhiyun  * is the command.
345*4882a593Smuzhiyun  */
346*4882a593Smuzhiyun 
ps2_sliced_command(struct ps2dev * ps2dev,u8 command)347*4882a593Smuzhiyun int ps2_sliced_command(struct ps2dev *ps2dev, u8 command)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun 	int i;
350*4882a593Smuzhiyun 	int retval;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	ps2_begin_command(ps2dev);
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	retval = __ps2_command(ps2dev, NULL, PS2_CMD_SETSCALE11);
355*4882a593Smuzhiyun 	if (retval)
356*4882a593Smuzhiyun 		goto out;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	for (i = 6; i >= 0; i -= 2) {
359*4882a593Smuzhiyun 		u8 d = (command >> i) & 3;
360*4882a593Smuzhiyun 		retval = __ps2_command(ps2dev, &d, PS2_CMD_SETRES);
361*4882a593Smuzhiyun 		if (retval)
362*4882a593Smuzhiyun 			break;
363*4882a593Smuzhiyun 	}
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun out:
366*4882a593Smuzhiyun 	dev_dbg(&ps2dev->serio->dev, "%02x - %d\n", command, retval);
367*4882a593Smuzhiyun 	ps2_end_command(ps2dev);
368*4882a593Smuzhiyun 	return retval;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun EXPORT_SYMBOL(ps2_sliced_command);
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun /*
373*4882a593Smuzhiyun  * ps2_init() initializes ps2dev structure
374*4882a593Smuzhiyun  */
375*4882a593Smuzhiyun 
ps2_init(struct ps2dev * ps2dev,struct serio * serio)376*4882a593Smuzhiyun void ps2_init(struct ps2dev *ps2dev, struct serio *serio)
377*4882a593Smuzhiyun {
378*4882a593Smuzhiyun 	mutex_init(&ps2dev->cmd_mutex);
379*4882a593Smuzhiyun 	lockdep_set_subclass(&ps2dev->cmd_mutex, serio->depth);
380*4882a593Smuzhiyun 	init_waitqueue_head(&ps2dev->wait);
381*4882a593Smuzhiyun 	ps2dev->serio = serio;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun EXPORT_SYMBOL(ps2_init);
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun /*
386*4882a593Smuzhiyun  * ps2_handle_ack() is supposed to be used in interrupt handler
387*4882a593Smuzhiyun  * to properly process ACK/NAK of a command from a PS/2 device.
388*4882a593Smuzhiyun  */
389*4882a593Smuzhiyun 
ps2_handle_ack(struct ps2dev * ps2dev,u8 data)390*4882a593Smuzhiyun bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun 	switch (data) {
393*4882a593Smuzhiyun 	case PS2_RET_ACK:
394*4882a593Smuzhiyun 		ps2dev->nak = 0;
395*4882a593Smuzhiyun 		break;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	case PS2_RET_NAK:
398*4882a593Smuzhiyun 		ps2dev->flags |= PS2_FLAG_NAK;
399*4882a593Smuzhiyun 		ps2dev->nak = PS2_RET_NAK;
400*4882a593Smuzhiyun 		break;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	case PS2_RET_ERR:
403*4882a593Smuzhiyun 		if (ps2dev->flags & PS2_FLAG_NAK) {
404*4882a593Smuzhiyun 			ps2dev->flags &= ~PS2_FLAG_NAK;
405*4882a593Smuzhiyun 			ps2dev->nak = PS2_RET_ERR;
406*4882a593Smuzhiyun 			break;
407*4882a593Smuzhiyun 		}
408*4882a593Smuzhiyun 		/* Fall through */
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	/*
411*4882a593Smuzhiyun 	 * Workaround for mice which don't ACK the Get ID command.
412*4882a593Smuzhiyun 	 * These are valid mouse IDs that we recognize.
413*4882a593Smuzhiyun 	 */
414*4882a593Smuzhiyun 	case 0x00:
415*4882a593Smuzhiyun 	case 0x03:
416*4882a593Smuzhiyun 	case 0x04:
417*4882a593Smuzhiyun 		if (ps2dev->flags & PS2_FLAG_WAITID) {
418*4882a593Smuzhiyun 			ps2dev->nak = 0;
419*4882a593Smuzhiyun 			break;
420*4882a593Smuzhiyun 		}
421*4882a593Smuzhiyun 		fallthrough;
422*4882a593Smuzhiyun 	default:
423*4882a593Smuzhiyun 		/*
424*4882a593Smuzhiyun 		 * Do not signal errors if we get unexpected reply while
425*4882a593Smuzhiyun 		 * waiting for an ACK to the initial (first) command byte:
426*4882a593Smuzhiyun 		 * the device might not be quiesced yet and continue
427*4882a593Smuzhiyun 		 * delivering data.
428*4882a593Smuzhiyun 		 * Note that we reset PS2_FLAG_WAITID flag, so the workaround
429*4882a593Smuzhiyun 		 * for mice not acknowledging the Get ID command only triggers
430*4882a593Smuzhiyun 		 * on the 1st byte; if device spews data we really want to see
431*4882a593Smuzhiyun 		 * a real ACK from it.
432*4882a593Smuzhiyun 		 */
433*4882a593Smuzhiyun 		dev_dbg(&ps2dev->serio->dev, "unexpected %#02x\n", data);
434*4882a593Smuzhiyun 		ps2dev->flags &= ~PS2_FLAG_WAITID;
435*4882a593Smuzhiyun 		return ps2dev->flags & PS2_FLAG_ACK_CMD;
436*4882a593Smuzhiyun 	}
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	if (!ps2dev->nak) {
439*4882a593Smuzhiyun 		ps2dev->flags &= ~PS2_FLAG_NAK;
440*4882a593Smuzhiyun 		if (ps2dev->cmdcnt)
441*4882a593Smuzhiyun 			ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1;
442*4882a593Smuzhiyun 	}
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	ps2dev->flags &= ~PS2_FLAG_ACK;
445*4882a593Smuzhiyun 	wake_up(&ps2dev->wait);
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	if (data != PS2_RET_ACK)
448*4882a593Smuzhiyun 		ps2_handle_response(ps2dev, data);
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	return true;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun EXPORT_SYMBOL(ps2_handle_ack);
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun /*
455*4882a593Smuzhiyun  * ps2_handle_response() is supposed to be used in interrupt handler
456*4882a593Smuzhiyun  * to properly store device's response to a command and notify process
457*4882a593Smuzhiyun  * waiting for completion of the command.
458*4882a593Smuzhiyun  */
459*4882a593Smuzhiyun 
ps2_handle_response(struct ps2dev * ps2dev,u8 data)460*4882a593Smuzhiyun bool ps2_handle_response(struct ps2dev *ps2dev, u8 data)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun 	if (ps2dev->cmdcnt)
463*4882a593Smuzhiyun 		ps2dev->cmdbuf[--ps2dev->cmdcnt] = data;
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	if (ps2dev->flags & PS2_FLAG_CMD1) {
466*4882a593Smuzhiyun 		ps2dev->flags &= ~PS2_FLAG_CMD1;
467*4882a593Smuzhiyun 		if (ps2dev->cmdcnt)
468*4882a593Smuzhiyun 			wake_up(&ps2dev->wait);
469*4882a593Smuzhiyun 	}
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	if (!ps2dev->cmdcnt) {
472*4882a593Smuzhiyun 		ps2dev->flags &= ~PS2_FLAG_CMD;
473*4882a593Smuzhiyun 		wake_up(&ps2dev->wait);
474*4882a593Smuzhiyun 	}
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	return true;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun EXPORT_SYMBOL(ps2_handle_response);
479*4882a593Smuzhiyun 
ps2_cmd_aborted(struct ps2dev * ps2dev)480*4882a593Smuzhiyun void ps2_cmd_aborted(struct ps2dev *ps2dev)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun 	if (ps2dev->flags & PS2_FLAG_ACK)
483*4882a593Smuzhiyun 		ps2dev->nak = 1;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	if (ps2dev->flags & (PS2_FLAG_ACK | PS2_FLAG_CMD))
486*4882a593Smuzhiyun 		wake_up(&ps2dev->wait);
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	/* reset all flags except last nack */
489*4882a593Smuzhiyun 	ps2dev->flags &= PS2_FLAG_NAK;
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun EXPORT_SYMBOL(ps2_cmd_aborted);
492