Solved Making i2c ELAN touchpad work (ELAN0D07:00 04F3:3078 on A3511)

First impression: the touchpad just works, out of the box. There is a core pointer in X, and the mouse can be moved. Great.

Second impression: not so great. There is no proper way to scroll the content of an xterm, there is no proper way to resize them, the xterm menus (ctrl + left/middle/right button) are entirely malfunctioning, and tipping the touchpad does weird things in unexpected moments.

Then there are lots of articles about configuring the touchpad, whether one should use xf86-input-libinput or xf86-input-evdev or xf86-input-synaptics or whatever, and with what options. But, libinput and evdev show all the same behaviour, and synaptics doesn't react on the device, and if explicitely forced to, states that it doesn't understand the protocol.

The problem appears to be that the device is presented to X as a mouse, not as a touchpad - from the log:
Code:
[  1004.804] (II) event5  - ELAN0D07:00 04F3:3078 Mouse: is tagged by udev as: Mouse
[  1004.809] (II) event5  - ELAN0D07:00 04F3:3078 Mouse: device is a pointer
And this is consistent with libinput list-devices:
Code:
Device:           ELAN0D07:00 04F3:3078 Mouse
Kernel:           /dev/input/event5
Group:            6
Seat:             seat0, default
Capabilities:     pointer

Then again there are lots of artices about how to make a touchpad actually be a touchpad and not just a simple mouse - but these circle around the configurations of ums and psm - and there is neither on the system.
What is actually on the system is this:
Code:
# devinfo
  acpi0
    pcib0
      pci0
        ig4iic0
          iicbus0
            iichid0
              hidbus0
                hms0
                hconf0
In hconf(4) there is something interesting, that looks like it would solve the problem (but it doesn't):
dev.hconf.*.input_mode
HID device input mode: 0 = mouse, 3 = touchpad.
When setting this to 3, the thing does just become non-functioning, no more mouse movement in X.

Now, is the problem with X, or with the device? This can be figured out, because /dev/input/event5 seems to be a character device; it just produces output that can be read with cat.
And when setting dev.hconf.0.input_mode=3, it does no longer produce any output.The problem is not with X.

Searching further into the hid + hidbus stuff, I found this wonderful article.

Only, it doesn't apply here. I have these XF86AudioMute. XF86AudioLowerVolume, XF86AudioRaiseVolume, and they send their events, without any hid device driver present! And I have a calculator key, that immediately starts xcalc, without anything configured (in icewm).

And I also have keys for Brightness up/down, Microphone, Mouse, ECO, and Radio-Kill - and these never send events, be there a hid driver or not.

This does not help further, it only shows that things can be different on various platforms.

But then there is this article
and that explains a bit. So, we apparently have a hms driver, and that is supposed to provide mice. And we have a hmt driver, that supports touchpads - but that comes from a different source and works somehow differently. Anyway, that one doesn't find any device here.

But then we also have a hidraw driver. Ad that can be kldloaded, and it works, and creates a /dev/hidraw0:
Code:
[2306] hidraw0: <ELAN0D07:00 04F3:3078 Raw HID Device> on hidbus0

And then we have usbhidctl, and, despite the name, it works on that file and delivers some output:
Code:
# usbhidctl -f /dev/hidraw0 -avl
Got input report 1 (12 bytes): 01 00 eb 0b 00 00 00 00 00 00 00 00
Generic_Desktop:Mouse.Generic_Desktop:Pointer.Button:Button_1=0
Generic_Desktop:Mouse.Generic_Desktop:Pointer.Button:Button_2=0
Generic_Desktop:Mouse.Generic_Desktop:Pointer.Generic_Desktop:X=-21
Generic_Desktop:Mouse.Generic_Desktop:Pointer.Generic_Desktop:Y=11
...

Now switching to dev.hconf.0.input_mode=3. I see these instead:
Code:
# usbhidctl -f /dev/hidraw0 -avl
Got input report 4 (12 bytes): 04 03 9d 08 d2 04 9e c5 01 80 27 55
Digitizer:Touch_Pad.Digitizer:Finger.Digitizer:Touch_Valid=1
Digitizer:Touch_Pad.Digitizer:Finger.Digitizer:Tip_Switch=1
Digitizer:Touch_Pad.Digitizer:Finger.Button:Button_2=0
Digitizer:Touch_Pad.Digitizer:Finger.Button:Button_3=0
Digitizer:Touch_Pad.Digitizer:Finger.Digitizer:Contact_Identifier=0
Digitizer:Touch_Pad.Digitizer:Finger.Generic_Desktop:X=2205
Digitizer:Touch_Pad.Digitizer:Finger.Generic_Desktop:Y=1234
Digitizer:Touch_Pad.Digitizer:0x0056=50590
Digitizer:Touch_Pad.Digitizer:Contact_Count=1

On that level things seem to work and make sense...
 
Let's look into the hmt driver code.It does indeed try to attach the touchpad, but then there is this:
And that is where it breaks and reports HMT_TYPE_UNSUPPORTED.

Just removing these two lines has an effect. Now there is this:
Code:
# devinfo
  acpi0
    pcib0
      pci0
        ig4iic0
          iicbus0
            iichid0
              hidbus0
                hms0
                hmt0
                hconf0
And there is this:
Code:
[133] hmt0: <ELAN0D07:00 04F3:3078 TouchPad> on hidbus0
[133] hmt0: Multitouch touchpad with 0 external buttons
[133] hmt0: 5 contacts with [C] properties. Report range [0:0] - [3110:1686]

And in X is now this:
Code:
[   837.539] (II) event5  - ELAN0D07:00 04F3:3078 Mouse: is tagged by udev as: Mouse
[   837.544] (II) event5  - ELAN0D07:00 04F3:3078 Mouse: device is a pointer
[   837.554] (II) event6  - ELAN0D07:00 04F3:3078 TouchPad: is tagged by udev as: Mouse Touchpad
[   837.584] (II) event6  - ELAN0D07:00 04F3:3078 TouchPad: device is a touchpad

And things do work a lot better now. There is a two-finger scroll that works. Resizing the windows works. Moving the windows works. The left xterm menu also works. What does not work is the buttons, so no middle/right menu - and no pasting the clipboard, for now.
 
Fixing the remainings. The problem is with this line: https://cgit.freebsd.org/src/tree/sys/dev/hid/hmt.c#n755
For whatever reason my device has this info in collevel 2, not 1.

Code:
--- a/sys/dev/hid/hmt.c
+++ b/sys/dev/hid/hmt.c
@@ -752,7 +752,7 @@ hmt_hid_parse(struct hmt_softc *sc, const void *d_ptr, hid_size_t d_len,
                                sc->int_btn_loc = hi.loc;
                                break;
                        }
-                       if (hi.collevel == 1 &&
+                       if (hi.collevel == 2 &&
                            hi.usage >= HID_USAGE2(HUP_BUTTON, left_btn) &&
                            hi.usage <= HID_USAGE2(HUP_BUTTON, HMT_BTN_MAX)) {
                                btn = (hi.usage & 0xFFFF) - left_btn;

Now the buttons work. But tapping does no longer. This, however, is due to the pseudo-AI of X - it has buttons, so apparently tapping is now considered unnecessary.
That can be fixed in the usual way, as described in this thread:
 
And I also have keys for Brightness up/down, Microphone, Mouse, ECO, and Radio-Kill - and these never send events, be there a hid driver or not.
This is getting still more interesting. These additional keys do not seem to generate an event with X. But, they do generate an event in the acpi_ec!

I came across this only by accident. I always get these ugly errors:
Code:
acpi_ec0: EcCommand: no response to 0x84
acpi_ec0: EcCommand: no response to 0x84
acpi_ec0: GPE query failed: AE_NO_HARDWARE_RESPONSE

I would have just switched the acpi_ec off - but then I don't see my battery status. So I thought, when I'm done with the more imminent things, I look into the code, what is going on there.
What is going on, is weird.

First, what is the acpi_ec?There is a good explanation: https://queue.acm.org/blogposting.cfm?id=18995

As this article explains, this EC can create events, so called GPE. And our OS is then responsible for handling these events. This code lives in sys/dev/acpica/acpi_ec.c
It works in this fashion: every time a GPE arrives, a counter is incremented. And then there is a code loop that processes them, and for each loop it decrements the counter.

As it seems, does my EC not like this treatment. After one event is sucessfully handled, it does not want another to be done, and goes into timeout. At that point I still thought that the thing is only handling the battery, and decided to just remove the loop - if then occasionally an event gets lost, that doesn't hurt.

Then I stumbled over that "hotkeys" word in the beforementioned article. And indeed my debug messages do print different values for these various keys. So, I'm having the keypress events now played into my hand, while I am sitting inside the kernel. What can be done from here?
 
Could you provide HID report descriptor from your touchpad?
Install sysutils/hid-tools, kldload hidraw.ko and post output of sudo hid-decode /dev/hidraw# where # corresponds to touchpad device node number
 
Back
Top