sebanc / brunch

Boot ChromeOS on x86_64 PC - Supports Intel CPU/GPU from 8th gen or AMD Ryzen
GNU General Public License v3.0
3.62k stars 389 forks source link

[HELP and TEST needed] Tablet mode detection with Intel VBTN #764

Open midi1996 opened 3 years ago

midi1996 commented 3 years ago

Currently the way brunch detects if it should enable tablet mode on Chrome OS is by checking either the USB IDs found in 99-tablet_mode.sh or use your own as stated in 99-hid_tablet_mode.sh. Intel Virtual Button is a device that Windows uses for many actions like "Modern Sleep" power button, volume keys and tablet mode detection among other things. Some other devices (like Lenovo Yoga and some Thinkpads with switchable modes) have another device that outputs those modes through thinkpad_acpi events.

This thread is about creating a way to use this detection method when possible (as it's probably more general and standardized).

I started checking this repo https://github.com/alesguzik/linux_detect_tablet_mode/ which is mainly for thinkpads but also had information about other devices (like the Dell XPS 9365) which use Intel VBTN.

My first test is with this script:

#!/bin/bash

device='/dev/input/by-path/pci-0000:00:1f.0-platform-INT33D6:00-event'
event_tablet_on='value cc'
event_tablet_off='value cd'

evtest "$device" | while read line; do
    case $line in
        *"$event_tablet_off"* ) echo "TABET_OFF"; echo 0 > /sys/bus/platform/devices/tablet_mode_switch.0/tablet_mode ;;
        *"$event_tablet_on"* ) echo "TABLET_ON"; echo 1 > /sys/bus/platform/devices/tablet_mode_switch.0/tablet_mode ;;
    esac
done

I used values that I got from my device (HP Elite X2 1012 G2). I would like you to test and share your values with me to see if there is any pattern we can use to create a better solution.

Issues I'm facing:

1: At boot, I have no way to detect if the device is in tablet mode or not until I physically move the keyboard. As far as my research goes I've seen some posts requiring the usage of libinput which isn't implemented in Chrome OS to begin with.


How to test: (for people with intel_vbtn, no idea for thinkpad users)

  1. Boot into a fairly recent linux distribution
  2. Check if intel_vbtn is loaded in lsmod
    • You can also check evtest by running it and you'll get a list with Intel Virtual Button driver entry (remember its number)
    • You can also check by running cat /proc/bus/input/devices | grep -i "virtual button"
  3. Run evtest and then type the number of the Intel Virtual Button driver event
  4. Detach/attach or flip your keyboard and get the log, remember which values are printed and when
  5. Share the information here.

Information to share:

Example:

Any help and suggestions is welcome.

sebanc commented 3 years ago

Thanks to your investigations, I think I can fix this properly.

Could you post the output of "cat /sys/class/dmi/id/chassis_type" and attach a dmesg ?

midi1996 commented 3 years ago

dmesg_log.txt

here is the dmesg

and the chassis type is 30

sebanc commented 3 years ago

Could you try tablet mode on the new brunch-unstable build (without any tablet mode framework option) ?

librehat commented 2 years ago

@sebanc: I'm more than happy to test this with a slightly different device (Samsung Galaxy Book Pro 360).

cat /sys/class/dmi/id/chassis_type shows 31. The latest r101 brunch framework doesn't switch on tablet mode when folded (however the keyword would be deactivated).

I also find that lsmod doesn't have intel_vbtn module loaded (Kernel 5.15)

librehat commented 2 years ago

What I found out is that /dev/input/by-path/platform-INTC1051:00-event will have an event with code=1, value=1 when tablet mode should be activated, and code=1, value=0 when it should be deactivated.

/dev/input/by-path/platform-INTC1051:00-event seems also used in Samsung Galaxy Book Flex (mine is Galaxy Book Pro 360. It might be a fair guess that it's also used for other convertible Samsung Galaxy Book products)

librehat commented 2 years ago

I wrote a small C program that can trigger the tablet mode automatically on my Samsung Galaxy Book Pro 360 (hopefully this can provide a good clue to enable tablet mode from brunch framework).

#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <string.h>
#include <stdio.h>

int main(void)
{
    const char *dev = "/dev/input/by-path/platform-INTC1051:00-event";
    const char *tablet_mode_dev = "/sys/bus/platform/devices/tablet_mode_switch.0/tablet_mode";
    struct input_event ev;
    ssize_t n;
    int fd;

    fd = open(dev, O_RDONLY);
    if (fd == -1) {
        fprintf(stderr, "Cannot open %s: %s.\n", dev, strerror(errno));
        return EXIT_FAILURE;
    }
    FILE *t_fd = fopen(tablet_mode_dev, "w");
    if (t_fd == NULL) {
        fprintf(stderr, "Cannot open %s: %s.\n", tablet_mode_dev, strerror(errno));
        return EXIT_FAILURE;
    }

    while (1) {
        n = read(fd, &ev, sizeof ev);
        if (n == (ssize_t)-1) {
            if (errno == EINTR)
                continue;
            else
                break;
        } else
        if (n != sizeof ev) {
            errno = EIO;
            break;
        }
        printf("Value=%d 0x%04x (%d)\n", ev.value, (int)ev.code, (int)ev.code);
        if (ev.code == 1) {  // tablet mode switch
            if (fprintf(t_fd, "%d", ev.value) < 0) {
                fprintf(stderr, "Failed to update tablet mode\n");
            }
            fflush(t_fd);
            printf("Tablet mode switch %d\n", ev.value);
        }
    }
    fflush(stdout);
    fprintf(stderr, "%s.\n", strerror(errno));
    return EXIT_FAILURE;
}

For people trying to use it in the meantime, make sure you change the permission of /sys/bus/platform/devices/tablet_mode_switch.0/tablet_mode so it doesn't require root privilege.