Skip to content

Commit c4c7eac

Browse files
committed
Input: libps2 - introduce common interrupt handler
Instead of exposing inner workings of libps2 to drivers such as atkbd and psmouse, have them define pre-receive and receive callbacks, and provide a common handler that can be used with underlying serio port. While at this add kerneldoc to the module. Link: https://lore.kernel.org/r/ZGK81cxqjr/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 7d674f9 commit c4c7eac

File tree

4 files changed

+269
-152
lines changed

4 files changed

+269
-152
lines changed

drivers/input/keyboard/atkbd.c

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -399,46 +399,60 @@ static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code
399399
}
400400

401401
/*
402-
* atkbd_interrupt(). Here takes place processing of data received from
403-
* the keyboard into events.
402+
* Tries to handle frame or parity error by requesting the keyboard controller
403+
* to resend the last byte. This historically not done on x86 as controllers
404+
* there typically do not implement this command.
404405
*/
405-
406-
static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
407-
unsigned int flags)
406+
static bool __maybe_unused atkbd_handle_frame_error(struct ps2dev *ps2dev,
407+
u8 data, unsigned int flags)
408408
{
409-
struct atkbd *atkbd = atkbd_from_serio(serio);
410-
struct input_dev *dev = atkbd->dev;
411-
unsigned int code = data;
412-
int scroll = 0, hscroll = 0, click = -1;
413-
int value;
414-
unsigned short keycode;
409+
struct atkbd *atkbd = container_of(ps2dev, struct atkbd, ps2dev);
410+
struct serio *serio = ps2dev->serio;
415411

416-
dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags);
417-
418-
#if !defined(__i386__) && !defined (__x86_64__)
419-
if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
412+
if ((flags & (SERIO_FRAME | SERIO_PARITY)) &&
413+
(~flags & SERIO_TIMEOUT) &&
414+
!atkbd->resend && atkbd->write) {
420415
dev_warn(&serio->dev, "Frame/parity error: %02x\n", flags);
421416
serio_write(serio, ATKBD_CMD_RESEND);
422417
atkbd->resend = true;
423-
goto out;
418+
return true;
424419
}
425420

426421
if (!flags && data == ATKBD_RET_ACK)
427422
atkbd->resend = false;
423+
424+
return false;
425+
}
426+
427+
static enum ps2_disposition atkbd_pre_receive_byte(struct ps2dev *ps2dev,
428+
u8 data, unsigned int flags)
429+
{
430+
struct serio *serio = ps2dev->serio;
431+
432+
dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags);
433+
434+
#if !defined(__i386__) && !defined (__x86_64__)
435+
if (atkbd_handle_frame_error(ps2dev, data, flags))
436+
return PS2_IGNORE;
428437
#endif
429438

430-
if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK))
431-
if (ps2_handle_ack(&atkbd->ps2dev, data))
432-
goto out;
439+
return PS2_PROCESS;
440+
}
433441

434-
if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_CMD))
435-
if (ps2_handle_response(&atkbd->ps2dev, data))
436-
goto out;
442+
static void atkbd_receive_byte(struct ps2dev *ps2dev, u8 data)
443+
{
444+
struct serio *serio = ps2dev->serio;
445+
struct atkbd *atkbd = container_of(ps2dev, struct atkbd, ps2dev);
446+
struct input_dev *dev = atkbd->dev;
447+
unsigned int code = data;
448+
int scroll = 0, hscroll = 0, click = -1;
449+
int value;
450+
unsigned short keycode;
437451

438452
pm_wakeup_event(&serio->dev, 0);
439453

440454
if (!atkbd->enabled)
441-
goto out;
455+
return;
442456

443457
input_event(dev, EV_MSC, MSC_RAW, code);
444458

@@ -460,35 +474,35 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
460474
case ATKBD_RET_BAT:
461475
atkbd->enabled = false;
462476
serio_reconnect(atkbd->ps2dev.serio);
463-
goto out;
477+
return;
464478
case ATKBD_RET_EMUL0:
465479
atkbd->emul = 1;
466-
goto out;
480+
return;
467481
case ATKBD_RET_EMUL1:
468482
atkbd->emul = 2;
469-
goto out;
483+
return;
470484
case ATKBD_RET_RELEASE:
471485
atkbd->release = true;
472-
goto out;
486+
return;
473487
case ATKBD_RET_ACK:
474488
case ATKBD_RET_NAK:
475489
if (printk_ratelimit())
476490
dev_warn(&serio->dev,
477491
"Spurious %s on %s. "
478492
"Some program might be trying to access hardware directly.\n",
479493
data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
480-
goto out;
494+
return;
481495
case ATKBD_RET_ERR:
482496
atkbd->err_count++;
483497
dev_dbg(&serio->dev, "Keyboard on %s reports too many keys pressed.\n",
484498
serio->phys);
485-
goto out;
499+
return;
486500
}
487501

488502
code = atkbd_compat_scancode(atkbd, code);
489503

490504
if (atkbd->emul && --atkbd->emul)
491-
goto out;
505+
return;
492506

493507
keycode = atkbd->keycode[code];
494508

@@ -564,8 +578,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
564578
}
565579

566580
atkbd->release = false;
567-
out:
568-
return IRQ_HANDLED;
569581
}
570582

571583
static int atkbd_set_repeat_rate(struct atkbd *atkbd)
@@ -1229,7 +1241,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
12291241
goto fail1;
12301242

12311243
atkbd->dev = dev;
1232-
ps2_init(&atkbd->ps2dev, serio);
1244+
ps2_init(&atkbd->ps2dev, serio,
1245+
atkbd_pre_receive_byte, atkbd_receive_byte);
12331246
INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
12341247
mutex_init(&atkbd->mutex);
12351248

@@ -1385,7 +1398,7 @@ static struct serio_driver atkbd_drv = {
13851398
},
13861399
.description = DRIVER_DESC,
13871400
.id_table = atkbd_serio_ids,
1388-
.interrupt = atkbd_interrupt,
1401+
.interrupt = ps2_interrupt,
13891402
.connect = atkbd_connect,
13901403
.reconnect = atkbd_reconnect,
13911404
.disconnect = atkbd_disconnect,

drivers/input/mouse/psmouse-base.c

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -336,17 +336,14 @@ static void psmouse_handle_oob_data(struct psmouse *psmouse, u8 data)
336336
}
337337
}
338338

339-
/*
340-
* psmouse_interrupt() handles incoming characters, either passing them
341-
* for normal processing or gathering them as command response.
342-
*/
343-
static irqreturn_t psmouse_interrupt(struct serio *serio,
344-
u8 data, unsigned int flags)
339+
static enum ps2_disposition psmouse_pre_receive_byte(struct ps2dev *ps2dev,
340+
u8 data,
341+
unsigned int flags)
345342
{
346-
struct psmouse *psmouse = psmouse_from_serio(serio);
343+
struct psmouse *psmouse = container_of(ps2dev, struct psmouse, ps2dev);
347344

348345
if (psmouse->state == PSMOUSE_IGNORE)
349-
goto out;
346+
return PS2_IGNORE;
350347

351348
if (unlikely((flags & SERIO_TIMEOUT) ||
352349
((flags & SERIO_PARITY) &&
@@ -357,27 +354,25 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
357354
"bad data from KBC -%s%s\n",
358355
flags & SERIO_TIMEOUT ? " timeout" : "",
359356
flags & SERIO_PARITY ? " bad parity" : "");
360-
ps2_cmd_aborted(&psmouse->ps2dev);
361-
goto out;
357+
return PS2_ERROR;
362358
}
363359

364360
if (flags & SERIO_OOB_DATA) {
365361
psmouse_handle_oob_data(psmouse, data);
366-
goto out;
362+
return PS2_IGNORE;
367363
}
368364

369-
if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_ACK))
370-
if (ps2_handle_ack(&psmouse->ps2dev, data))
371-
goto out;
365+
return PS2_PROCESS;
366+
}
372367

373-
if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_CMD))
374-
if (ps2_handle_response(&psmouse->ps2dev, data))
375-
goto out;
368+
static void psmouse_receive_byte(struct ps2dev *ps2dev, u8 data)
369+
{
370+
struct psmouse *psmouse = container_of(ps2dev, struct psmouse, ps2dev);
376371

377-
pm_wakeup_event(&serio->dev, 0);
372+
pm_wakeup_event(&ps2dev->serio->dev, 0);
378373

379374
if (psmouse->state <= PSMOUSE_RESYNCING)
380-
goto out;
375+
return;
381376

382377
if (psmouse->state == PSMOUSE_ACTIVATED &&
383378
psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
@@ -386,7 +381,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
386381
psmouse->badbyte = psmouse->packet[0];
387382
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
388383
psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
389-
goto out;
384+
return;
390385
}
391386

392387
psmouse->packet[psmouse->pktcnt++] = data;
@@ -395,21 +390,21 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
395390
if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {
396391
if (psmouse->pktcnt == 1) {
397392
psmouse->last = jiffies;
398-
goto out;
393+
return;
399394
}
400395

401396
if (psmouse->packet[1] == PSMOUSE_RET_ID ||
402397
(psmouse->protocol->type == PSMOUSE_HGPK &&
403398
psmouse->packet[1] == PSMOUSE_RET_BAT)) {
404399
__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
405-
serio_reconnect(serio);
406-
goto out;
400+
serio_reconnect(ps2dev->serio);
401+
return;
407402
}
408403

409404
/* Not a new device, try processing first byte normally */
410405
psmouse->pktcnt = 1;
411406
if (psmouse_handle_byte(psmouse))
412-
goto out;
407+
return;
413408

414409
psmouse->packet[psmouse->pktcnt++] = data;
415410
}
@@ -424,14 +419,11 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
424419
psmouse->badbyte = psmouse->packet[0];
425420
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
426421
psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
427-
goto out;
422+
return;
428423
}
429424

430425
psmouse->last = jiffies;
431426
psmouse_handle_byte(psmouse);
432-
433-
out:
434-
return IRQ_HANDLED;
435427
}
436428

437429
/*
@@ -1604,7 +1596,8 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
16041596
if (!psmouse || !input_dev)
16051597
goto err_free;
16061598

1607-
ps2_init(&psmouse->ps2dev, serio);
1599+
ps2_init(&psmouse->ps2dev, serio,
1600+
psmouse_pre_receive_byte, psmouse_receive_byte);
16081601
INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync);
16091602
psmouse->dev = input_dev;
16101603
snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys);
@@ -1786,7 +1779,7 @@ static struct serio_driver psmouse_drv = {
17861779
},
17871780
.description = DRIVER_DESC,
17881781
.id_table = psmouse_serio_ids,
1789-
.interrupt = psmouse_interrupt,
1782+
.interrupt = ps2_interrupt,
17901783
.connect = psmouse_connect,
17911784
.reconnect = psmouse_reconnect,
17921785
.fast_reconnect = psmouse_fast_reconnect,

0 commit comments

Comments
 (0)