]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Input: serio - add hangup support
authorHans Verkuil <hverkuil@xs4all.nl>
Thu, 4 Aug 2016 18:16:23 +0000 (11:16 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Wed, 21 Sep 2016 14:57:11 +0000 (07:57 -0700)
The Pulse-Eight USB CEC adapter is a usb device that shows up as a ttyACM0
device.  It requires that you run inputattach in order to communicate with
it via serio.

This all works well, but it would be nice to have a udev rule to
automatically start inputattach. That too works OK, but the problem comes
when the USB device is unplugged: the tty hangup is never handled by the
serio framework so the inputattach utility never exits and you have to kill
it manually.

By adding this hangup callback the inputattach utility now properly exits
as soon as the USB device is unplugged.

The udev rule I used on my Debian sid system is:

SUBSYSTEM=="tty", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="2548", ATTRS{idProduct}=="1002", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="pulse8-cec-inputattach@%k.service"

And /etc/systemd/system/pulse8-cec-inputattach@.service is as follows:

===============================================================
[Unit]
Description=inputattach for pulse8-cec device on %I

[Service]
Type=simple
ExecStart=/usr/local/bin/inputattach --pulse8-cec /dev/%I
KillMode=process
===============================================================

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Tested-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/serio/serport.c

index 9c927d35c1f5d71c4822e4f9e5310ce8a6562876..d189843f3727c52ad360f8f704bb06d6397160f5 100644 (file)
@@ -71,10 +71,7 @@ static void serport_serio_close(struct serio *serio)
 
        spin_lock_irqsave(&serport->lock, flags);
        clear_bit(SERPORT_ACTIVE, &serport->flags);
-       set_bit(SERPORT_DEAD, &serport->flags);
        spin_unlock_irqrestore(&serport->lock, flags);
-
-       wake_up_interruptible(&serport->wait);
 }
 
 /*
@@ -248,6 +245,19 @@ static long serport_ldisc_compat_ioctl(struct tty_struct *tty,
 }
 #endif
 
+static int serport_ldisc_hangup(struct tty_struct *tty)
+{
+       struct serport *serport = (struct serport *) tty->disc_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&serport->lock, flags);
+       set_bit(SERPORT_DEAD, &serport->flags);
+       spin_unlock_irqrestore(&serport->lock, flags);
+
+       wake_up_interruptible(&serport->wait);
+       return 0;
+}
+
 static void serport_ldisc_write_wakeup(struct tty_struct * tty)
 {
        struct serport *serport = (struct serport *) tty->disc_data;
@@ -274,6 +284,7 @@ static struct tty_ldisc_ops serport_ldisc = {
        .compat_ioctl = serport_ldisc_compat_ioctl,
 #endif
        .receive_buf =  serport_ldisc_receive,
+       .hangup =       serport_ldisc_hangup,
        .write_wakeup = serport_ldisc_write_wakeup
 };