Guest User

Autorotate to tablet mode for Linux

a guest
Dec 23rd, 2018
590
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 8.21 KB | None | 0 0
  1. #!/usr/bin/env bash
  2. # tivasyk <[email protected]>
  3. # License: GPU GPL v3
  4.  
  5. # Settings
  6. # --------
  7. # It's probably a good idea to verify these prior to first use of the script and
  8. # modify if necessary.
  9.  
  10. # IIO devices path (Linux industrial I/O subsystem)
  11. # One probably does not need to change this
  12. # iio_devices_path - path to the iio devices buffer tree
  13. # iio_devices_name - the file containing device name
  14. iio_devices_path="/sys/bus/iio/devices/iio:device"
  15. iio_devices_name="name"
  16.  
  17. # Accelerometer device path and sensor files
  18. # accel_device_name - what we expect to find in the ../iio:deviceX/name file
  19. # accel_device_path - will be populated by identify_device(), may be set to override
  20. # accel_sensor_x - the channel file of the axis to check for screen rotation (x,y,z)
  21. accel_device_name="accel_3d"
  22. accel_device_path=""
  23. accel_sensor_x="in_accel_x_raw"
  24. accel_sensor_y="in_accel_y_raw"
  25. accel_sensor_z="in_accel_z_raw"
  26.  
  27. # Current display that will be rotated. This will be populated automatically
  28. # with the name of connected output (xrandr) by the script if left empty.
  29. # Otherwise one can fill this in manually to omit automatical detection
  30. xdisplay=""
  31.  
  32. # Input devices (touchpad and touchscreen)
  33. # One probably needs to run xinput --list to verify the names of the input devices
  34. # actually present and modify these variables accordingly. Leaving one of them blank
  35. # will omit rotation for that device.
  36. touchpad=''
  37. touchscreen='SYNAPTICS Synaptics Touch Digitizer V04'
  38.  
  39. # Error codes
  40. error_arguments=1   # Incorrect argument(s) either to the script or a function
  41. error_device=2      # Accelerometer device path or folder structure not found?
  42. error_sensor=3      # Accelerometer sensor channel file $accel_sensor not found?
  43.  
  44. # Functions
  45. # ---------
  46. show_help() {
  47.     local NAME
  48.     NAME=$(basename "$0")
  49.     cat <<EOF
  50. $NAME is a shell script that will check the IIO accelerometer sensor and turn to tablet or laptop mode: set the screen and touchscreen orientation according to rotation, launch onboard keyboard.
  51.  
  52. Usage: $NAME [--cont [<interval>]] [--help]
  53.  
  54.     -h, --help  Print this help and quit
  55.     -c, --cont  Run continuously at specified interval (default 1s)
  56.  
  57. Example: $NAME --cont 2 &   # Run the script in the background at 2s intervals
  58.    
  59. NOTE: The script has only been tested on Acer Aspire R13 (R7-371T) transformer laptop.
  60. EOF
  61. }
  62.  
  63. identify_device() {
  64.     # Will look for the device whose name is given as the only argument,
  65.     # by comparing the devices names in /sys/bus/iio/devices/iio:deviceX/name
  66.     # file and return the path to the device folder.
  67.     # Relies on the devices_path variable set in the Setting section.
  68.     # Process arguments:
  69.     if [[ $# -eq 0 ]]; then
  70.         # Incorrect arguments
  71.         exit ${error_arguments}
  72.     else
  73.         local device_name="${1}"
  74.     fi
  75.     # Loop through all devices and check names:
  76.     local device
  77.     for device in "${iio_devices_path}"* ; do
  78.         if [[ $(cat "${device}/${iio_devices_name}") == "${device_name}" ]]; then
  79.             echo "${device}"
  80.         fi
  81.     done
  82. }
  83.  
  84. read_accelerometer() {
  85.     # The first argument is obligatory and should specify one axis
  86.     # of the accelerometer device: -x, -y or -z
  87.     # Also --raw will not try to decode the reading.
  88.     # Process arguments:
  89.     if [[ $# -eq 0 ]]; then
  90.         # Incorrect arguments
  91.         exit ${error_arguments}
  92.     else
  93.         while [[ "$*" != "" ]]; do
  94.             local accel_sensor=${accel_sensor_x}
  95.             case "$1" in
  96.                 # Check for --raw option
  97.                 "-r"|"--raw" ) local option_raw=1 ; shift ;;
  98.                 # Select accelerometer axis (-x is default)
  99.                 "-x" ) shift ;;
  100.                 "-y" ) accel_sensor=${accel_sensor_y} ; shift ;;
  101.                 "-z" ) accel_sensor=${accel_sensor_z} ; shift ;;
  102.                 # Ignore any other options
  103.                 * ) shift ;;
  104.             esac
  105.         done
  106.     fi
  107.     # Read the sensor:
  108.     if [[ -f "${accel_device_path}/${accel_sensor}" ]]; then
  109.         local reading ; reading=$(cat "${accel_device_path}/${accel_sensor}")
  110.     else
  111.         # No sensor file found?
  112.         exit ${error_sensor}
  113.     fi
  114.     # Decode the reading
  115.     # It's a 16-bit signed integer, but reads as a string
  116.     # 1..1000 : positive angle (0-90°)
  117.     # 65575..54576 : negative angle (0-90°)
  118.     local max_reading=1000
  119.     local max_positive=32767
  120.     local max_integer=65535
  121.     # Decode reading into degrees (unless option_raw in set)
  122.     if [[ -z ${option_raw} ]]; then
  123.         if [[ ${reading} -gt ${max_positive} ]]; then
  124.             echo "$(((reading - max_integer) / (max_reading / 90)))"
  125.         else
  126.             echo "$((reading / (max_reading / 90)))"
  127.         fi        
  128.     else
  129.         echo "${reading}"
  130.     fi
  131. }
  132.  
  133. rotate_screen() {
  134.     # Will try to rotate the display and input devices, using:
  135.     # xrandr to rotate the display picture;
  136.     # xinput to rotate the touchpad and touchscreen (via Coordinate Transformation Matrix).
  137.     # Relies on touchpad and touchscreen variables set in the Settings section.
  138.     # Rotate the display:
  139.     xrandr --output $1 --rotate $2
  140.     # Rotate the input devices
  141.     transform='Coordinate Transformation Matrix'
  142.     case "$2" in
  143.         normal)
  144.         [ ! -z "$touchpad" ]    && xinput set-prop "$touchpad"    "$transform" 1 0 0 0 1 0 0 0 1
  145.         [ ! -z "$touchscreen" ] && xinput set-prop "$touchscreen" "$transform" 1 0 0 0 1 0 0 0 1
  146.         ;;
  147.         inverted)
  148.         [ ! -z "$touchpad" ]    && xinput set-prop "$touchpad"    "$transform" -1 0 1 0 -1 1 0 0 1
  149.         [ ! -z "$touchscreen" ] && xinput set-prop "$touchscreen" "$transform" -1 0 1 0 -1 1 0 0 1
  150.         ;;
  151.         left)
  152.         [ ! -z "$touchpad" ]    && xinput set-prop "$touchpad"    "$transform" 0 -1 1 1 0 0 0 0 1
  153.         [ ! -z "$touchscreen" ] && xinput set-prop "$touchscreen" "$transform" 0 -1 1 1 0 0 0 0 1
  154.         ;;
  155.         right)
  156.         [ ! -z "$touchpad" ]    && xinput set-prop "$touchpad"    "$transform" 0 1 0 -1 0 1 0 0 1
  157.         [ ! -z "$touchscreen" ] && xinput set-prop "$touchscreen" "$transform" 0 1 0 -1 0 1 0 0 1
  158.         ;;
  159.     esac
  160. }
  161.  
  162. main() {
  163.     # Process arguments
  164.     while [[ "$*" != "" ]]; do
  165.         case "$1" in
  166.             "-h"|"--help" )
  167.                 show_help
  168.                 exit 0
  169.                 ;;
  170.             "-c"|"--cont" )
  171.                 # Check next argument for repeat interval
  172.                 option_cont=1
  173.                 shift
  174.                 if [[ ! -z "$1" && -z "${1//[0-9.]/}" ]]; then
  175.                     option_cont="$1"
  176.                     shift
  177.                 fi
  178.                 ;;
  179.             * )
  180.                 ;;
  181.         esac
  182.     done
  183.     # Identify the current display to be rotated
  184.     if [[ "${xdisplay}" == "" ]]; then
  185.         xdisplay=`xrandr --current | grep " connected" | sed -e 's/ .*//g'`
  186.     fi
  187.     # Identify the accelerometer device, unless the accel_device_path has been set manually
  188.     if [[ "${accel_device_path}" == "" ]]; then
  189.         accel_device_path=$(identify_device ${accel_device_name})
  190.     fi
  191.     # Run the test
  192.     while true ; do
  193.         # Get the screen rotation angle from the accelerometer sensor
  194.         angle_x=$(read_accelerometer -x)
  195.         angle_y=$(read_accelerometer -y)
  196.         angle_z=$(read_accelerometer -z)
  197.         # Check orientation
  198.         if [[ ${angle_z//-/} -lt 80 && ${angle_x} -gt 20 ]]; then
  199.             echo "Screen orientation: left (x=${angle_x}, y=${angle_y}, z=${angle_z})"
  200.             rotate_screen ${xdisplay} left
  201.         elif [[ ${angle_z//-/} -lt 80 && ${angle_x} -lt -20 ]]; then
  202.             echo "Screen orientation: right (x=${angle_x}, y=${angle_y}, z=${angle_z})"
  203.             rotate_screen ${xdisplay} right
  204.         elif [[ ${angle_y//-/} -gt 20 && ${angle_x//-/} -lt 20 ]]; then
  205.             echo "Screen orientation: normal (x=${angle_x}, y=${angle_y}, z=${angle_z})"
  206.             rotate_screen ${xdisplay} normal
  207.         else
  208.             echo "Screen orientation: keep (x=${angle_x}, y=${angle_y}, z=${angle_z})"
  209.         fi
  210.         # Run continuously (option_cont)?
  211.         if [[ "${option_cont}" == "" ]]; then
  212.            exit 0
  213.         else
  214.         sleep ${option_cont}
  215.         fi
  216.      done
  217. }
  218.  
  219. main "$@"
Advertisement
Add Comment
Please, Sign In to add comment