mohamed-badaoui / asus-touchpad-numpad-driver

Activate Numpad inside the touchpad with top right corner switch
301 stars 70 forks source link

ZenBook Pro Duo UX581 #36

Closed Joan-Tondo closed 3 years ago

Joan-Tondo commented 3 years ago

Hello everybody!!! I tried to adapt the script for touchpad with % and = for the ZenBook Pro Duo UX581 with Manjaro kernel 12 asus-zenbook-pro-duo-touchpad2 I recalculate cols and rows sizes and I putted the events following the image. After that I got a problem with the % I could reproduce the % sending an InputEvent(EV_KEY.KEY_LEFTSHIFT, 1) plus an InputEvent(EV_KEY.KEY_5, 1) but after write in the screen the first %, the system makes a very little pause and begins to write a lot of % till I click another character in the touchpad. After that, the % doesn't write anything more and the keyboard respond badly. The rest of the touchpad characters follows fine.

The code modified:

` import re import subprocess import sys from fcntl import F_SETFL, fcntl from os import O_NONBLOCK from subprocess import PIPE, Popen from time import sleep

from libevdev import EV_ABS, EV_KEY, EV_LED, EV_SYN, Device, InputEvent

tries=5

Look into the devices file

while tries > 0:

keyboard_detected = 0
touchpad_detected = 0

with open('/proc/bus/input/devices', 'r') as f:

    lines = f.readlines()
    for line in lines:
        # Look for the touchpad #
        if touchpad_detected == 0 and ("Name=\"ASUE" in line or "Name=\"ELAN" in line) and "Touchpad" in line:
            touchpad_detected = 1

        if touchpad_detected == 1:
            if "S: " in line:
                # search device id 
                device_id=re.sub(r".*i2c-([^/])/.*$", r'\1', line).replace("\n", "")

            if "H: " in line:
                touchpad = line.split("event")[1]
                touchpad = touchpad.split(" ")[0]
                touchpad_detected = 2

        # Look for the keyboard (numlock) # AT Translated Set OR Asus Keyboard
        if keyboard_detected == 0 and ("Name=\"AT Translated Set 2 keyboard" in line or "Name=\"Asus Keyboard" in line):
            keyboard_detected = 1

        if keyboard_detected == 1:
            if "H: " in line:
                keyboard = line.split("event")[1]
                keyboard = keyboard.split(" ")[0]
                keyboard_detected = 2

        # Stop looking if both have been found #
        if keyboard_detected == 2 and touchpad_detected == 2:
            break

if keyboard_detected != 2 or touchpad_detected != 2:
    tries -= 1
    if tries == 0:
        if keyboard_detected != 2:
            print("Can't find keyboard, code " + str(keyboard_detected))
        if touchpad_detected != 2:
            print("Can't find touchpad, code " + str(touchpad_detected))
        if touchpad_detected == 2 and not device_id.isnumeric():
            print("Can't find device id")
        sys.exit(1)
else:
    break

sleep(0.1)

Start monitoring the touchpad

fd_t = open('/dev/input/event' + str(touchpad), 'rb') fcntl(fd_t, F_SETFL, O_NONBLOCK) d_t = Device(fd_t)

Retrieve touchpad dimensions

ai = d_t.absinfo[EV_ABS.ABS_X] (minx, maxx) = (ai.minimum, ai.maximum) ai = d_t.absinfo[EV_ABS.ABS_Y] (miny, maxy) = (ai.minimum, ai.maximum)

Start monitoring the keyboard (numlock)

fd_k = open('/dev/input/event' + str(keyboard), 'rb') fcntl(fd_k, F_SETFL, O_NONBLOCK) d_k = Device(fd_k)

Create a new keyboard device to send numpad events

dev = Device() dev.name = "Asus Touchpad/Numpad" dev.enable(EV_KEY.KEY_KP1) dev.enable(EV_KEY.KEY_KP2) dev.enable(EV_KEY.KEY_KP3) dev.enable(EV_KEY.KEY_KP4) dev.enable(EV_KEY.KEY_KP5) dev.enable(EV_KEY.KEY_5) dev.enable(EV_KEY.KEY_KP6) dev.enable(EV_KEY.KEY_KP7) dev.enable(EV_KEY.KEY_KP8) dev.enable(EV_KEY.KEY_KP9) dev.enable(EV_KEY.KEY_KP0) dev.enable(EV_KEY.KEY_BACKSPACE) dev.enable(EV_KEY.KEY_KPSLASH) dev.enable(EV_KEY.KEY_KPASTERISK) dev.enable(EV_KEY.KEY_KPMINUS) dev.enable(EV_KEY.KEY_KPPLUS) dev.enable(EV_KEY.KEY_KPCOMMA) dev.enable(EV_KEY.KEY_KPENTER) dev.enable(EV_KEY.KEY_LEFTSHIFT) dev.enable(EV_KEY.KEY_NUMLOCK) dev.enable(EV_KEY.KEY_APOSTROPHE) dev.enable(EV_KEY.KEY_KPDOT) dev.enable(EV_KEY.KEY_KPEQUAL)

udev = dev.create_uinput_device() finger = 0 value = 0

onCmd = "i2ctransfer -f -y " + device_id + " w13@0x15 0x05 0x00 0x3d 0x03 0x06 0x00 0x07 0x00 0x0d 0x14 0x03 0x01 0xad" offCmd = "i2ctransfer -f -y " + device_id + " w13@0x15 0x05 0x00 0x3d 0x03 0x06 0x00 0x07 0x00 0x0d 0x14 0x03 0x00 0xad"

def activate_numlock(): events = [ InputEvent(EV_KEY.KEY_NUMLOCK, 1), InputEvent(EV_SYN.SYN_REPORT, 0) ] udev.send_events(events) d_t.grab() subprocess.call(onCmd, shell=True)

def deactivate_numlock(): events = [ InputEvent(EV_KEY.KEY_NUMLOCK, 0), InputEvent(EV_SYN.SYN_REPORT, 0) ] udev.send_events(events) d_t.ungrab() subprocess.call(offCmd, shell=True)

numlock=False

Process events while running

while True:

# If keyboard sends numlock event with F8 key tap, enable/disable touchpad events #
for e in d_k.events():
    if e.matches(EV_KEY.KEY_F8) and e.value == 1:
        numlock = not numlock
        if numlock:
            activate_numlock()
        else:
            deactivate_numlock()

# If touchpad sends tap events, convert x/y position to numlock key and send it #
for e in d_t.events():
    # ignore others events, except position and finger events 
    if not (
        e.matches(EV_ABS.ABS_MT_POSITION_X) or 
        e.matches(EV_ABS.ABS_MT_POSITION_Y) or 
        e.matches(EV_KEY.BTN_TOOL_FINGER)
    ):
        continue

    # Get x position #
    if e.matches(EV_ABS.ABS_MT_POSITION_X):
        x = e.value
        continue
    # Get y position #
    if e.matches(EV_ABS.ABS_MT_POSITION_Y):
        y = e.value
        continue

    # If tap #
    if e.matches(EV_KEY.BTN_TOOL_FINGER):
        # If end of tap, send release key event #
        if e.value == 0:
            finger = 0
            try:
                if value:
                    events = [
                        InputEvent(EV_KEY.KEY_LEFTSHIFT, 0),
                        InputEvent(value, 0),
                        InputEvent(EV_SYN.SYN_REPORT, 0)
                    ]
                    udev.send_events(events)
                    value = None
                pass
            except OSError as e:
                pass

        # Start of tap #
        if finger == 0 and e.value == 1:
            finger = 1

    # Check if numlock was hit #
    if (
        e.matches(EV_KEY.BTN_TOOL_FINGER) and 
        e.value == 1 and 
        (x > 0.95 * maxx) and (y < 0.05 * maxy)
    ):
        finger=0
        numlock = not numlock
        if numlock:
            activate_numlock()
        else:
            deactivate_numlock()

    # If touchpad mode, ignore #
    if not numlock:
        continue

    # During tap #
    if finger == 1:
        finger = 2
        try:
            # first zero row
            #if y < 0.13 * maxy:
            #   if x < 0.499 * maxx:
            #        value = EV_KEY.KEY_APOSTROPHE
            #    else:
            #        value = EV_KEY.KEY_F8
            # first row
            if y < 0.293 * maxy:
                if x < 0.273 * maxx:
                    value = EV_KEY.KEY_KPEQUAL
                elif x < 0.499 * maxx:
                    value = EV_KEY.KEY_APOSTROPHE
                else:
                    value = EV_KEY.KEY_BACKSPACE
            # second row
            elif y < 0.456 * maxy:
                if x < 0.273 * maxx:
                    value = EV_KEY.KEY_KP7
                elif x < 0.499 * maxx:
                    value = EV_KEY.KEY_KP8
                elif x < 0.725 * maxx:
                    value = EV_KEY.KEY_KP9
                else:
                    value = EV_KEY.KEY_KPSLASH
            # third row
            elif y < 0.619 * maxy:
                if x < 0.273 * maxx:
                    value = EV_KEY.KEY_KP4
                elif x < 0.499 * maxx:
                    value = EV_KEY.KEY_KP5
                elif x < 0.725 * maxx:
                    value = EV_KEY.KEY_KP6
                else:
                    value = EV_KEY.KEY_KPASTERISK
            # fourth row
            elif y < 0.782 * maxy:
                if x < 0.273 * maxx:
                    value = EV_KEY.KEY_KP1
                elif x < 0.499 * maxx:
                    value = EV_KEY.KEY_KP2
                elif x < 0.725 * maxx:
                    value = EV_KEY.KEY_KP3
                else:
                    value = EV_KEY.KEY_KPMINUS
            # fifth row
            #elif y < 0.945 * maxy:
            else :
                if x < 0.25 * maxx:
                    value = EV_KEY.KEY_KP0
                elif x < 0.499 * maxx:
                    value = EV_KEY.KEY_KPDOT
                elif x < 0.725 * maxx:
                    value = EV_KEY.KEY_KPENTER
                else:
                    value = EV_KEY.KEY_KPPLUS
            # last zero row
            #else :

            # Send press key event #
            if value == EV_KEY.KEY_APOSTROPHE :
                events = [
                        InputEvent(EV_KEY.KEY_LEFTSHIFT, 1),
                        InputEvent(EV_KEY.KEY_5, 1),
                        InputEvent(EV_SYN.SYN_REPORT, 0)
                ]
                value = 0
            else:
                events = [
                    InputEvent(value, 1),
                    InputEvent(EV_SYN.SYN_REPORT, 0)
                ]
            udev.send_events(events)
        except OSError as e:
            pass
sleep(0.1)

Close file descriptors

fd_k.close() fd_t.close() `

Moreover, I had to modify the service because the gnome doesn't start till I click Alt+F2, command line, startx:

` [Unit] Description=Asus Touchpad to Numpad Handler After=graphical.target

[Service] ExecStart=/usr/bin/python3 /usr/bin/asus_touchpad_numpad.py

[Install] WantedBy=graphical.target `

Thanks

mohamed-badaoui commented 3 years ago

Hi,

Please consider to use Stackoverflow for any technical question, We here mainly to try to resolve any issue with the current driver for the supported models. If you want to contribute to evolve this for a new model, please consider a pull request.

Thanks for your comprehension.