Missing support for touchscreen input event "BTN_TOUCH"

Hi,

I’m using SDL2.0.7 with a Raspberry Pi 3 and its standard 7" touchscreen display. I build SDL from sources on the Pi.

Everything works out of the box except for one unhandled input event of type EV_KEY with code BTN_TOUCH. Whenever I touch the screen I receive this warning on stdout:

INFO: The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL forums/mailing list <https ://discourse.libsdl.org/> EVDEV KeyCode 330

The specific touchscreen I’m using supports multiple contacts, so to be a bit more precise: I receive the warning once when putting my first finger down and once when releasing my last finger.

This warning is generated in the call to SDL_EVDEV_translate_keycode() located in SDL2-2.0.7/src/core/linux/SDL_evdev.c line 267. Since it’s an EV_KEY event SDL assumes that this event is keyboard generated input but can’t/doesn’t map the linux virtual key code BTN_TOUCH (330) to any SDL_SCANCODE* in SDL2-2.0.7/src/events/scancodes_linux.h.

I was wondering why and where this keyboard event was generated by my touch device, here is what I found.

Using evtest I get this device profile for my touch device:

$ evtest /dev/input/event2
Input driver version is 1.0.1
Input device ID: bus 0x0 vendor 0x0 product 0x0 version 0x0
Input device name: "FT5406 memory based driver"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 330 (BTN_TOUCH)
  Event type 3 (EV_ABS)
    Event code 0 (ABS_X)
      Value    509
      Min        0
      Max      800
    Event code 1 (ABS_Y)
      Value    141
      Min        0
      Max      480
    Event code 47 (ABS_MT_SLOT)
      Value      1
      Min        0
      Max        9
    Event code 53 (ABS_MT_POSITION_X)
      Value      0
      Min        0
      Max      800
    Event code 54 (ABS_MT_POSITION_Y)
      Value      0
      Min        0
      Max      480
    Event code 57 (ABS_MT_TRACKING_ID)
      Value      0
      Min        0
      Max    65535
Properties:
  Property type 1 (INPUT_PROP_DIRECT)

So in linux kernel terminology (https ://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt) it’s a type B multi-touch device, indicated by:

ABS_MT_SLOT
ABS_MT_POSITION_X
ABS_MT_POSITION_Y
ABS_MT_TRACKING_ID

but it’s also a legacy pointer emulated device, indicated by the presence of:

BTN_TOUCH
ABS_X
ABS_Y

The three legacy events (BTN_TOUCH, ABS_X and ABS_Y) are generated by the kernel driver rpi-ft5406 of my touchscreen when it calls kernel function input_mt_report_pointer_emulation() which is documented here.

So the legacy events are correct behaviour of my touchscreen driver and I cannot switch it off. Other touchscreen drivers might generate them, too, so it’s not really a problem tied to the Raspberry Pi or my specific touchscreen, this might also occur in different linux touch-device configurations.

Here is an event log where I put one finger down, move then release (note how the kernel driver sends both new and old event sets):

Event: time 1514649017.140701, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 0
Event: time 1514649017.140701, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 162
Event: time 1514649017.140701, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 191
Event: time 1514649017.140701, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 225
Event: time 1514649017.140701, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1514649017.140701, type 3 (EV_ABS), code 0 (ABS_X), value 191
Event: time 1514649017.140701, type 3 (EV_ABS), code 1 (ABS_Y), value 225
Event: time 1514649017.140701, -------------- SYN_REPORT ------------
Event: time 1514649017.300665, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 195
Event: time 1514649017.300665, type 3 (EV_ABS), code 0 (ABS_X), value 195
Event: time 1514649017.300665, -------------- SYN_REPORT ------------
Event: time 1514649017.340666, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 214
Event: time 1514649017.340666, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 227
Event: time 1514649017.340666, type 3 (EV_ABS), code 0 (ABS_X), value 214
Event: time 1514649017.340666, type 3 (EV_ABS), code 1 (ABS_Y), value 227
Event: time 1514649017.340666, -------------- SYN_REPORT ------------
Event: time 1514649017.380662, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 226
Event: time 1514649017.380662, type 3 (EV_ABS), code 0 (ABS_X), value 226
Event: time 1514649017.380662, -------------- SYN_REPORT ------------
Event: time 1514649017.420665, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 239
Event: time 1514649017.420665, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 228
Event: time 1514649017.420665, type 3 (EV_ABS), code 0 (ABS_X), value 239
Event: time 1514649017.420665, type 3 (EV_ABS), code 1 (ABS_Y), value 228
Event: time 1514649017.420665, -------------- SYN_REPORT ------------
Event: time 1514649017.460689, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 249
Event: time 1514649017.460689, type 3 (EV_ABS), code 0 (ABS_X), value 249
Event: time 1514649017.460689, -------------- SYN_REPORT ------------
Event: time 1514649017.500661, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 257
Event: time 1514649017.500661, type 3 (EV_ABS), code 0 (ABS_X), value 257
Event: time 1514649017.500661, -------------- SYN_REPORT ------------
Event: time 1514649017.540665, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 262
Event: time 1514649017.540665, type 3 (EV_ABS), code 0 (ABS_X), value 262
Event: time 1514649017.540665, -------------- SYN_REPORT ------------
Event: time 1514649017.580665, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 263
Event: time 1514649017.580665, type 3 (EV_ABS), code 0 (ABS_X), value 263
Event: time 1514649017.580665, -------------- SYN_REPORT ------------
Event: time 1514649017.740662, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value -1
Event: time 1514649017.740662, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1514649017.740662, -------------- SYN_REPORT ------------

Here’s a log where I put two fingers down (one-two-one-none, note how ABS_X and ABS_Y only change when the first finger location changes):

Event: time 1514649055.420678, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 0
Event: time 1514649055.420678, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 165
Event: time 1514649055.420678, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 160
Event: time 1514649055.420678, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 321
Event: time 1514649055.420678, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1514649055.420678, type 3 (EV_ABS), code 0 (ABS_X), value 160
Event: time 1514649055.420678, type 3 (EV_ABS), code 1 (ABS_Y), value 321
Event: time 1514649055.420678, -------------- SYN_REPORT ------------
Event: time 1514649055.660664, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 163
Event: time 1514649055.660664, type 3 (EV_ABS), code 0 (ABS_X), value 163
Event: time 1514649055.660664, -------------- SYN_REPORT ------------
Event: time 1514649055.700666, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 170
Event: time 1514649055.700666, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 319
Event: time 1514649055.700666, type 3 (EV_ABS), code 0 (ABS_X), value 170
Event: time 1514649055.700666, type 3 (EV_ABS), code 1 (ABS_Y), value 319
Event: time 1514649055.700666, -------------- SYN_REPORT ------------
Event: time 1514649055.860665, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 196
Event: time 1514649055.860665, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 312
Event: time 1514649055.860665, type 3 (EV_ABS), code 0 (ABS_X), value 196
Event: time 1514649055.860665, type 3 (EV_ABS), code 1 (ABS_Y), value 312
Event: time 1514649055.860665, -------------- SYN_REPORT ------------
Event: time 1514649055.940665, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 197
Event: time 1514649055.940665, type 3 (EV_ABS), code 0 (ABS_X), value 197
Event: time 1514649055.940665, -------------- SYN_REPORT ------------
Event: time 1514649056.100661, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 1
Event: time 1514649056.100661, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 166
Event: time 1514649056.100661, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 389
Event: time 1514649056.100661, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 214
Event: time 1514649056.100661, -------------- SYN_REPORT ------------
Event: time 1514649056.180682, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 215
Event: time 1514649056.180682, -------------- SYN_REPORT ------------
Event: time 1514649056.260669, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 0
Event: time 1514649056.260669, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 198
Event: time 1514649056.260669, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 1
Event: time 1514649056.260669, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 388
Event: time 1514649056.260669, type 3 (EV_ABS), code 0 (ABS_X), value 198
Event: time 1514649056.260669, -------------- SYN_REPORT ------------
Event: time 1514649056.300657, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 389
Event: time 1514649056.300657, -------------- SYN_REPORT ------------
Event: time 1514649056.340667, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 0
Event: time 1514649056.340667, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 200
Event: time 1514649056.340667, type 3 (EV_ABS), code 0 (ABS_X), value 200
Event: time 1514649056.340667, -------------- SYN_REPORT ------------
Event: time 1514649056.580671, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 0
Event: time 1514649056.580671, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 240
Event: time 1514649056.580671, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 300
Event: time 1514649056.580671, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 1
Event: time 1514649056.580671, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 426
Event: time 1514649056.580671, type 3 (EV_ABS), code 0 (ABS_X), value 240
Event: time 1514649056.580671, type 3 (EV_ABS), code 1 (ABS_Y), value 300
Event: time 1514649056.580671, -------------- SYN_REPORT ------------
Event: time 1514649056.620673, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 0
Event: time 1514649056.620673, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 243
Event: time 1514649056.620673, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 299
Event: time 1514649056.620673, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 1
Event: time 1514649056.620673, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 430
Event: time 1514649056.620673, type 3 (EV_ABS), code 0 (ABS_X), value 243
Event: time 1514649056.620673, type 3 (EV_ABS), code 1 (ABS_Y), value 299
Event: time 1514649056.820665, -------------- SYN_REPORT ------------
Event: time 1514649057.020687, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 0
Event: time 1514649057.020687, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 249
Event: time 1514649057.020687, type 3 (EV_ABS), code 0 (ABS_X), value 249
Event: time 1514649057.020687, -------------- SYN_REPORT ------------
Event: time 1514649057.060667, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value -1
Event: time 1514649057.060667, type 3 (EV_ABS), code 0 (ABS_X), value 436
Event: time 1514649057.060667, type 3 (EV_ABS), code 1 (ABS_Y), value 217
Event: time 1514649057.060667, -------------- SYN_REPORT ------------
Event: time 1514649057.100667, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 1
Event: time 1514649057.100667, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 437
Event: time 1514649057.100667, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 218
Event: time 1514649057.100667, type 3 (EV_ABS), code 0 (ABS_X), value 437
Event: time 1514649057.100667, type 3 (EV_ABS), code 1 (ABS_Y), value 218
Event: time 1514649057.100667, -------------- SYN_REPORT ------------
Event: time 1514649057.140663, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 438
Event: time 1514649057.140663, type 3 (EV_ABS), code 0 (ABS_X), value 438
Event: time 1514649057.140663, -------------- SYN_REPORT ------------
Event: time 1514649057.540663, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 492
Event: time 1514649057.540663, type 3 (EV_ABS), code 0 (ABS_X), value 492
Event: time 1514649057.540663, -------------- SYN_REPORT ------------
Event: time 1514649057.660687, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value -1
Event: time 1514649057.660687, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1514649057.660687, -------------- SYN_REPORT ------------

So I see at least two possible quick fixes:

  1. Ignore BTN_TOUCH when it comes from a touch-device, just in the same way ABS_X and ABS_Y are currently already being ignored in the same case.
  2. Define a new scan code in SDL2-2.0.7/include/SDL_scancode.h (for example, SDL_SCANCODE_TOUCH), expand linux_scancode_table[] in SDL2-2.0.7/src/events/scancodes_linux.h by about 100 entries, and put the new scan code SDL_SCANCODE_TOUCH at position 330.

The first solution should not have any side effects. I tested it by inserting this code in SDL2-2.0.7/src/core/linux/SDL_evdev.c, line 265 (right before the comment Probably keyboard):

/* ignore BTN_TOUCH */
if (item->is_touchscreen && events[i].code == 330) {
    break;
}

I didn’t check it, but the second solution might have the side effect of waking the screen saver, which maybe is a nice feature. Since it introduces a new scan code it should also not have other side effects, and if that is the case then I guess it’s preferrable.

Thanks,
Christian.

Great description of the issue. I forgot to check discourse and only looked on bugzilla. I went through a similar process and came up with the same change as your first solution (make touchscreen ignore BTN_TOUCH). I submitted a patch at https://bugzilla.libsdl.org/show_bug.cgi?id=4174.