Skip to content

zForce touchscreen input device fails when closed and immediately reopened

Component

Type: Bug

Product/Category: JavaFX

Subcategory: Graphics

Release: 8 Update 111 (1.8.0_111)

Operating System: Ubuntu

Details

More details about the problem (★ indicates required fields).

★ Synopsis:

zForce touchscreen input device fails when closed and immediately reopened

Full OS version:

Ubuntu 14.04.5 LTS with Linux kernel: Linux koboa 2.6.35.3-850-gbc67621+ #604 PREEMPT Mon Oct 15 15:37:28 CST 2012 armv7l armv7l armv7l GNU/Linux.

Additional Configuration Information:

The Java VM is Oracle JDK 8 Update 111 for “Linux ARM 32 Hard Float ABI” with the armv7hf overlay bundle built from the OpenJFX 8 sources on October 27, 2016.

The test machine is a Kobo Touch N905C e-reader with 256 MB of RAM and the 800 MHz Freescale i.MX507 Multimedia Application Processor Model MCIMX507CVM8B (integrated electronic paper display, ARM Cortex-A8 core, ARMv7-A architecture, no OpenVG 2D graphics acceleration).

Install the Pango shared libraries with the command:

$ sudo apt-get install libpangoft2-1.0-0

Otherwise, you'll get the following error when starting the JavaFX application:

Exception in Application start method
java.lang.reflect.InvocationTargetException
...
Caused by: java.lang.RuntimeException:
    Exception in Application start method
...
Caused by: java.lang.UnsatisfiedLinkError:
    /home/john/opt/jdk1.8.0_111/jre/lib/arm/libjavafx_font_pango.so:
    libpangoft2-1.0.so.0: cannot open shared object file:
    No such file or directory

Development Kit or Runtime version:

$ ~/opt/jdk1.8.0_111/bin/java -version
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) Client VM (build 25.111-b14, mixed mode)

★ Description:

If the Neonode zForce touchscreen input device is quickly reopened with an “open, close, open” sequence, on rare occasions it works, but the great majority of times it fails. The driver receives the call to reopen the device before it finishes the previous call to close it, so the device remains deactivated.

The input device is initialized in the constructor of com.sun.glass.ui.monocle.LinuxInputDevice, where the method LinuxAbsoluteInputCapabilities.getCapabilities(File, BitSet) opens and closes the device but is followed immediately by a call to open it again.

this.absCaps = LinuxAbsoluteInputCapabilities.getCapabilities(
        devNode, capabilities.get("abs"));
fd = system.open(devNode.getPath(), LinuxSystem.O_RDONLY);
if (fd == -1) {
    throw new IOException(system.getErrorMessage() + " on " + devNode);
}

★ Frequency:

☐ Always
☒ Often
☐ Occasionally
☐ Rarely

Regression:

Unknown.

Steps to Reproduce:

The easiest way to reproduce the problem is with a Kobo Touch N905C e-reader and the OpenJFX Monocle EPD class library. Simply start a JavaFX application that has a button and check whether it responds to touch events.

Expected Result:

The JavaFX application should receive the touch events.

Actual Result:

The JavaFX application almost always fails to receive the touch events.

Error Message(s)/Crash Logs:

Use the dmesg command to read messages from Linux kernel ring buffer.

The following messages are logged to the kernel ring buffer when the touchscreen input device works:

[drivers/input/touchscreen/zforce_i2c.c-422] zforce_i2c_open()
[zForce_ir_touch_recv_data-145] command Activate (0) ...
[zForce_ir_touch_recv_data-154] command Resolution (0) ...
[zForce_ir_touch_recv_data-179] command Frequency (0) ...
[drivers/input/touchscreen/zforce_i2c.c-437] zforce_i2c_close()
[zForce_ir_touch_recv_data-142] command Deactivate ...
[drivers/input/touchscreen/zforce_i2c.c-422] zforce_i2c_open()
[zForce_ir_touch_recv_data-145] command Activate (0) ...
[zForce_ir_touch_recv_data-154] command Resolution (0) ...
[zForce_ir_touch_recv_data-179] command Frequency (0) ...

The following messages are logged when the device fails:

[drivers/input/touchscreen/zforce_i2c.c-422] zforce_i2c_open()
[zForce_ir_touch_recv_data-145] command Activate (0) ...
[zForce_ir_touch_recv_data-154] command Resolution (0) ...
[zForce_ir_touch_recv_data-179] command Frequency (0) ...
[drivers/input/touchscreen/zforce_i2c.c-437] zforce_i2c_close()
[drivers/input/touchscreen/zforce_i2c.c-422] zforce_i2c_open()
[zForce_ir_touch_recv_data-142] command Deactivate ...
[zForce_ir_touch_recv_data-198] command overrun (8) ...

Source code for an executable test case:

You can use the simple program below to reproduce the problem:

package org.status6.hello;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class HelloApp extends Application {

    private static final String TITLE = "Hello App";
    private static final String LABEL = "Say Hello";
    private static final String MESSAGE = "Hello World!";
    private static final int WIDTH = 800;
    private static final int HEIGHT = 600;

    @Override
    public void start(Stage stage) {
        Button button = new Button();
        button.setText(LABEL);
        button.setOnAction(e -> System.out.println(MESSAGE));

        StackPane root = new StackPane();
        root.getChildren().add(button);
        Scene scene = new Scene(root, WIDTH, HEIGHT);

        stage.setTitle(TITLE);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Package the program in a JAR file called hello.jar, place the file in ~/lib, and run it with the command:

$ sudo ~/bin/hello.sh

where hello.sh is the Bash script:

#!/bin/bash
# Runs the JavaFX Hello Application
export JAVA_HOME=$HOME/opt/jdk1.8.0_111

java_ext_dirs=$HOME/lib/ext:$JAVA_HOME/jre/lib/ext
java_library_path=$HOME/lib/arm:$JAVA_HOME/jre/lib/arm:/lib:/usr/lib

$JAVA_HOME/bin/java \
    -Djava.ext.dirs=$java_ext_dirs \
    -Djava.library.path=$java_library_path \
    -Dglass.platform=Monocle -Dmonocle.platform=EPD -Dprism.order=sw \
    -Dmonocle.input.18/0/0/0.minX=0 -Dmonocle.input.18/0/0/0.maxX=800 \
    -Dmonocle.input.18/0/0/0.minY=0 -Dmonocle.input.18/0/0/0.maxY=600 \
    -Dmonocle.input.18/0/0/0.flipXY=false \
    -jar $HOME/lib/hello.jar

You must run the script as root so that the program has permission to access the Linux input and framebuffer devices.

Workaround:

I modified the constructor for LinuxInputDevice so that the sequence of the device initialization is “open, open, close” by simply moving the call to LinuxAbsoluteInputCapabilities.getCapabilities after the call to open the device:

fd = system.open(devNode.getPath(), LinuxSystem.O_RDONLY);
if (fd == -1) {
    throw new IOException(system.getErrorMessage() + " on " + devNode);
}
this.absCaps = LinuxAbsoluteInputCapabilities.getCapabilities(
        devNode, capabilities.get("abs"));

With this change, the kernel does not close the input device on the call to close because the reference count for the device remains above zero. The input device is not deactivated, and the driver logs the following messages to the kernel ring buffer:

[drivers/input/touchscreen/zforce_i2c.c-422] zforce_i2c_open()
[zForce_ir_touch_recv_data-145] command Activate (0) ...
[zForce_ir_touch_recv_data-154] command Resolution (0) ...
[zForce_ir_touch_recv_data-179] command Frequency (0) ...

Note that because all of the fields in LinuxInputDevice are private, I am unable to create a subclass without reimplementing the parent class in its entirety.

★ Severity:

☐ Can not make any progress until this bug is resolved.
☒ Difficult to make even minimal progress without resolving this bug.
☐ Some progress is possible without resolving this bug.
☐ No Impact.

User Information

★ Your Name: John Neffenger

★ Company: Status Six Communications

★ Email: john@status6.com