diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a07b9cb1..36867ba3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,12 +16,12 @@ on: branches: [ main, develop ] jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu:24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Install Dependencies - run: ./deploy/dependencies/install_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh shell: bash - name: Build run: ./tests/test_kernel_build.sh @@ -31,12 +31,12 @@ jobs: shell: bash run-kernel-module-test: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Install Dependencies - run: ./deploy/dependencies/install_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh shell: bash - name: Test Install run: ./tests/test_kernel_install.sh @@ -49,12 +49,12 @@ jobs: shell: bash run-kernel-dkms-install-test: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Install Dependencies - run: ./deploy/dependencies/install_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh shell: bash - name: Build run: ./tests/test_kenel_dkms_install.sh || true @@ -62,12 +62,12 @@ jobs: run-tests: name: Run Tests - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Check out Git repository uses: actions/checkout@v4 - name: Install Development Dependencies - run: ./deploy/dependencies/install_development_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_development_dependencies_ubuntu_24_04.sh shell: bash - name: Lint with Linux checkpath if: always() @@ -92,7 +92,7 @@ jobs: check-kernel-module-change: needs: [build, run-kernel-module-test, run-kernel-dkms-install-test, run-tests] - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 outputs: output1: ${{ steps.filter.outputs.workflows }} steps: @@ -106,7 +106,7 @@ jobs: release-kernel-patch: needs: [check-kernel-module-change] - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: @@ -166,7 +166,7 @@ jobs: test-in-docker-container: needs: [build, run-tests] - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 @@ -175,7 +175,7 @@ jobs: shell: bash test-packages: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/build_PR.yml b/.github/workflows/build_PR.yml index 777e8c0e..26b1e657 100644 --- a/.github/workflows/build_PR.yml +++ b/.github/workflows/build_PR.yml @@ -5,12 +5,12 @@ on: branches: [ main ] jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Install Dependencies - run: ./deploy/dependencies/install_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh shell: bash - name: Build run: ./tests/test_kernel_build.sh @@ -20,12 +20,12 @@ jobs: shell: bash run-kernel-module-test: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Install Dependencies - run: ./deploy/dependencies/install_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh shell: bash - name: Test Install run: ./tests/test_kernel_install.sh @@ -38,12 +38,12 @@ jobs: shell: bash run-kernel-dkms-install-test: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Install Dependencies - run: ./deploy/dependencies/install_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh shell: bash - name: Build run: ./tests/test_kenel_dkms_install.sh || true @@ -51,12 +51,12 @@ jobs: run-tests: name: Run Tests - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Check out Git repository uses: actions/checkout@v4 - name: Install Development Dependencies - run: ./deploy/dependencies/install_development_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_development_dependencies_ubuntu_24_04.sh shell: bash - name: Lint with Linux checkpath if: always() @@ -81,7 +81,7 @@ jobs: check-kernel-module-change: needs: [build, run-kernel-module-test, run-kernel-dkms-install-test, run-tests] - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 outputs: output1: ${{ steps.filter.outputs.workflows }} steps: @@ -95,7 +95,7 @@ jobs: release-kernel-patch: needs: [check-kernel-module-change] - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: @@ -107,7 +107,7 @@ jobs: test-in-docker-container: needs: [build, run-tests] - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/extra.yaml b/.github/workflows/extra.yaml index 0c0c982b..616b9b7f 100644 --- a/.github/workflows/extra.yaml +++ b/.github/workflows/extra.yaml @@ -4,12 +4,12 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Install Dependencies - run: ./deploy/dependencies/install_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh shell: bash - name: Build run: ./tests/test_kernel_build.sh @@ -18,7 +18,7 @@ jobs: run: ./tests/test_kernel_install.sh shell: bash test-ci-env: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Setup upterm session diff --git a/.github/workflows/manual_test.yaml b/.github/workflows/manual_test.yaml index a6b17cfc..51651f50 100644 --- a/.github/workflows/manual_test.yaml +++ b/.github/workflows/manual_test.yaml @@ -14,12 +14,12 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Install Dependencies - run: ./deploy/dependencies/install_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh shell: bash - name: Build run: ./tests/test_kernel_build.sh @@ -29,12 +29,12 @@ jobs: shell: bash run-kernel-module-test: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Install Dependencies - run: ./deploy/dependencies/install_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh shell: bash - name: Test Install run: ./tests/test_kernel_install.sh @@ -47,12 +47,12 @@ jobs: shell: bash run-kernel-dkms-install-test: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Install Dependencies - run: ./deploy/dependencies/install_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh shell: bash - name: Build run: ./tests/test_kenel_dkms_install.sh || true @@ -60,12 +60,12 @@ jobs: run-tests: name: Run Tests - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Check out Git repository uses: actions/checkout@v4 - name: Install Development Dependencies - run: ./deploy/dependencies/install_development_dependencies_ubuntu.sh + run: ./deploy/dependencies/install_development_dependencies_ubuntu_24_04.sh shell: bash - name: Lint with Linux checkpath if: always() @@ -91,7 +91,7 @@ jobs: # Use to test kernel patch build if needed release-kernel-patch: needs: [build, run-kernel-module-test, run-kernel-dkms-install-test, run-tests] - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 if: ${{ github.event.inputs.BUILD_KERNEL_PATCH == 'true' }} steps: - uses: actions/checkout@v4 @@ -103,7 +103,7 @@ jobs: test-in-docker-container: needs: [build, run-tests] - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/deploy/Dockerfile.ubuntu b/deploy/Dockerfile.ubuntu.22.04 similarity index 78% rename from deploy/Dockerfile.ubuntu rename to deploy/Dockerfile.ubuntu.22.04 index 4b2e16b8..df054d6a 100644 --- a/deploy/Dockerfile.ubuntu +++ b/deploy/Dockerfile.ubuntu.22.04 @@ -20,11 +20,11 @@ RUN apt-get install -y gcc-12 RUN mkdir /opt/LinuxLegionLaptop WORKDIR /opt/LinuxLegionLaptop -COPY ./deploy/dependencies/install_dependencies_ubuntu.sh ./deploy/dependencies/install_dependencies_ubuntu.sh -RUN deploy/dependencies/install_dependencies_ubuntu.sh +COPY ./deploy/dependencies/install_dependencies_ubuntu_22_04.sh ./deploy/dependencies/install_dependencies_ubuntu_22_04.sh +RUN ./deploy/dependencies/install_dependencies_ubuntu_22_04.sh COPY ./deploy/dependencies ./deploy/dependencies -RUN deploy/dependencies/install_development_dependencies_ubuntu.sh +RUN ./deploy/dependencies/install_development_dependencies_ubuntu_22_04.sh COPY . /opt/LinuxLegionLaptop diff --git a/deploy/Dockerfile.ubuntu.24.04 b/deploy/Dockerfile.ubuntu.24.04 new file mode 100644 index 00000000..6786b3e9 --- /dev/null +++ b/deploy/Dockerfile.ubuntu.24.04 @@ -0,0 +1,38 @@ +FROM ubuntu:24.04 +ARG DEBIAN_FRONTEND=noninteractive + +# Install sudo (used in scripts that are tested) +RUN apt-get update && \ + apt-get -y install sudo + +# Set timezone (used by pylint) and locale +ENV LANG=en_US.UTF-8 +ENV LANGUAGE=en_US:en +ENV LC_ALL=en_US.UTF-8 +RUN ln -snf /usr/share/zoneinfo/US/Central /etc/localtime && echo US/Central > /etc/timezone && \ + apt-get -y install locales tzdata && \ + sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ + locale-gen + + +RUN apt-get install -y gcc-12 + +RUN mkdir /opt/LinuxLegionLaptop +WORKDIR /opt/LinuxLegionLaptop + +COPY ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh +RUN ./deploy/dependencies/install_dependencies_ubuntu_24_04.sh + +COPY ./deploy/dependencies ./deploy/dependencies +RUN ./deploy/dependencies/install_development_dependencies_ubuntu_24_04.sh + +COPY . /opt/LinuxLegionLaptop + +RUN tests/test_kernel_build.sh \ + && tests/test_kernel_install.sh +RUN tests/test_python_cli.sh +# && tests/test_python_gui.sh +RUN deploy/python_install_pip_pkg.sh \ + && tests/test_python_cli_installed.sh +# && tests/test_python_gui_installed.sh +#RUN tests/test_python_run_gui_root.sh diff --git a/deploy/dependencies/install_dependencies_ubuntu.sh b/deploy/dependencies/install_dependencies_ubuntu_22_04.sh similarity index 100% rename from deploy/dependencies/install_dependencies_ubuntu.sh rename to deploy/dependencies/install_dependencies_ubuntu_22_04.sh diff --git a/deploy/dependencies/install_dependencies_ubuntu_24_04.sh b/deploy/dependencies/install_dependencies_ubuntu_24_04.sh new file mode 100755 index 00000000..d4213713 --- /dev/null +++ b/deploy/dependencies/install_dependencies_ubuntu_24_04.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -ex +sudo apt-get update +sudo apt-get install -y make gcc clang linux-headers-$(uname -r) build-essential git lm-sensors wget python3-pyqt6 python3-yaml python3-venv python3-pip python3-wheel python3-argcomplete policykit-1 +sudo apt-get install -y dkms openssl mokutil diff --git a/deploy/dependencies/install_development_dependencies_ubuntu.sh b/deploy/dependencies/install_development_dependencies_ubuntu_22_04.sh similarity index 90% rename from deploy/dependencies/install_development_dependencies_ubuntu.sh rename to deploy/dependencies/install_development_dependencies_ubuntu_22_04.sh index 8d204717..e2228e13 100755 --- a/deploy/dependencies/install_development_dependencies_ubuntu.sh +++ b/deploy/dependencies/install_development_dependencies_ubuntu_22_04.sh @@ -14,5 +14,5 @@ sudo apt-get -y -qq install \ sudo pip install pyqt6-tools PyQt6 -${DIR}/install_dependencies_ubuntu.sh +${DIR}/install_dependencies_ubuntu_22_04.sh ${DIR}/linux_kernel/install_checkpath.sh diff --git a/deploy/dependencies/install_development_dependencies_ubuntu_24_04.sh b/deploy/dependencies/install_development_dependencies_ubuntu_24_04.sh new file mode 100755 index 00000000..b34f8245 --- /dev/null +++ b/deploy/dependencies/install_development_dependencies_ubuntu_24_04.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -ex +DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +# Needed in CI +sudo apt-get update + +# Linter +# Tools for running GUI tests headless +sudo apt-get -y -qq install \ + wget \ + pylint python3-venv python3-pip python3-build \ + python3-installer xvfb libxcb-xinerama0 pyqt6-dev-tools + +${DIR}/install_dependencies_ubuntu_24_04.sh +${DIR}/linux_kernel/install_checkpath.sh diff --git a/deploy/docker-compose.yaml b/deploy/docker-compose.yaml index 3e6fa295..6a72929d 100644 --- a/deploy/docker-compose.yaml +++ b/deploy/docker-compose.yaml @@ -18,10 +18,14 @@ services: # build: # context: .. # dockerfile: deploy/Dockerfile.suse - legion-ubuntu: + # legion-ubuntu-22-04: + # build: + # context: .. + # dockerfile: deploy/Dockerfile.ubuntu.22.04 + legion-ubuntu-24-04: build: context: .. - dockerfile: deploy/Dockerfile.ubuntu + dockerfile: deploy/Dockerfile.ubuntu.24.04 ubuntu: image: ubuntu:latest volumes: diff --git a/kernel_module/legion-laptop.c b/kernel_module/legion-laptop.c index e1c42bdb..49230cfe 100644 --- a/kernel_module/legion-laptop.c +++ b/kernel_module/legion-laptop.c @@ -97,8 +97,9 @@ MODULE_PARM_DESC( enable_platformprofile, "Enable the platform profile sysfs API to read and write the power mode."); +// TODO: remove this? #define LEGIONFEATURES \ - "fancurve powermode platformprofile platformprofilenotify minifancurve" + "fancurve powermode platformprofile platformprofilenotify minifancurve fancurve_pmw_speed fancurve_rpm_speed" //Size of fancurve stored in embedded controller #define MAXFANCURVESIZE 10 @@ -1428,9 +1429,9 @@ static int acpi_process_buffer_to_ints(const char *id_name, int id_nr, goto err; } -// Reduced verbosity (only printing when ACPI result have bad parameters) -// pr_info("ACPI result for %s:%d: ACPI buffer length: %u\n", id_name, -// id_nr, out->buffer.length); + // Reduced verbosity (only printing when ACPI result have bad parameters) + // pr_info("ACPI result for %s:%d: ACPI buffer length: %u\n", id_name, + // id_nr, out->buffer.length); for (i = 0; i < ressize; ++i) res[i] = out->buffer.pointer[i]; @@ -1814,7 +1815,7 @@ static ssize_t ecram_memoryio_read(const struct ecram_memoryio *ec_memoryio, * methods to access EC RAM. */ static ssize_t ecram_memoryio_write(const struct ecram_memoryio *ec_memoryio, - u16 ec_offset, u8 value) + u16 ec_offset, u8 value) { if (ec_offset < ec_memoryio->physical_ec_start) { pr_info("Unexpected write at offset %d into EC RAM\n", @@ -2011,7 +2012,8 @@ static void ecram_write(struct ecram *ecram, u16 ecram_offset, u8 value) } err = ecram_portio_write(&ecram->portio, ecram_offset, value); if (err) - pr_info("Error writing EC RAM to 0x%x: Read-Only.\n", ecram_offset); + pr_info("Error writing EC RAM to 0x%x: Read-Only.\n", + ecram_offset); } /* =============================== */ @@ -2063,11 +2065,19 @@ enum SENSOR_ATTR { /* Data model for fan curve */ /* ============================= */ +#define MAX_RPM 10000 + +enum fan_speed_unit { + FAN_SPEED_UNIT_PERCENT = 1, + FAN_SPEED_UNIT_PWM = 2, + FAN_SPEED_UNIT_RPM_HUNDRED = 3, +}; + struct fancurve_point { // rpm1 devided by 100 - u8 rpm1_raw; + u8 speed1; // rpm2 devided by 100 - u8 rpm2_raw; + u8 speed2; // >=2 , <=5 (lower is faster); must increase by level u8 accel; // >=2 , <=5 (lower is faster); must increase by level @@ -2110,6 +2120,7 @@ static const struct fancurve_point fancurve_point_zero = { 0, 0, 0, 0, 0, struct fancurve { struct fancurve_point points[MAXFANCURVESIZE]; + enum fan_speed_unit fan_speed_unit; // number of points used; must be <= MAXFANCURVESIZE size_t size; // the point at which fans are run currently @@ -2132,22 +2143,79 @@ static bool fancurve_is_valid_max_temp(int max_temp) // - make hwmon implementation easier // - keep fancurve valid, otherwise EC will not properly control fan -static bool fancurve_set_rpm1(struct fancurve *fancurve, int point_id, int rpm) +static bool fancurve_set_speed_pwm(struct fancurve *fancurve, int point_id, + int fan_id, int value) { - bool valid = point_id == 0 ? rpm == 0 : (rpm >= 0 && rpm <= 4500); + u8 *speed; - if (valid) - fancurve->points[point_id].rpm1_raw = rpm / 100; - return valid; + if (!(point_id == 0 ? value == 0 : (value >= 0 && value <= 255))) { + pr_err("Value %d PWM not in allowed range to point with id %d", + value, point_id); + return false; + } + if (!(point_id < fancurve->size && fan_id >= 0 && fan_id < 2)) { + pr_err("Setting point id %d, fan id %d not valid for fancurve with size %ld", + point_id, fan_id, fancurve->size); + return false; + } + speed = fan_id == 0 ? &fancurve->points[point_id].speed1 : + &fancurve->points[point_id].speed2; + + switch (fancurve->fan_speed_unit) { + case FAN_SPEED_UNIT_PERCENT: + *speed = clamp_t(u8, value * 100 / 255, 0, 255); + return true; + case FAN_SPEED_UNIT_PWM: + *speed = clamp_t(u8, value, 0, 255); + return true; + case FAN_SPEED_UNIT_RPM_HUNDRED: + *speed = clamp_t(u8, value * MAX_RPM / 100 / 255, 0, 255); + return true; + default: + pr_info("No method to set for fan_speed_unit %d.", + fancurve->fan_speed_unit); + return false; + } + return false; } -static bool fancurve_set_rpm2(struct fancurve *fancurve, int point_id, int rpm) +static bool fancurve_get_speed_pwm(const struct fancurve *fancurve, + int point_id, int fan_id, int *value) { - bool valid = point_id == 0 ? rpm == 0 : (rpm >= 0 && rpm <= 4500); + int speed; - if (valid) - fancurve->points[point_id].rpm2_raw = rpm / 100; - return valid; + pr_info("%s 1 point id=%d, fancurve=%p, fancurve.fan_speed_unit=%d, fancurve.size=%ld", + __func__, point_id, (void *) fancurve, fancurve->fan_speed_unit, fancurve->size); + + if (!(point_id < fancurve->size && fan_id >= 0 && fan_id < 2)) { + pr_err("Reading point id %d, fan id %d not valid for fancurve with size %ld", + point_id, fan_id, fancurve->size); + return false; + } + pr_info("%s 2", __func__); + + speed = fan_id == 0 ? fancurve->points[point_id].speed1 : + fancurve->points[point_id].speed2; + + switch (fancurve->fan_speed_unit) { + case FAN_SPEED_UNIT_PERCENT: + *value = speed * 255 / 100; + pr_info("%s 3a", __func__); + return true; + case FAN_SPEED_UNIT_PWM: + *value = speed; + pr_info("%s 3b", __func__); + return true; + case FAN_SPEED_UNIT_RPM_HUNDRED: + *value = speed * 255 * 100 / MAX_RPM; + pr_info("%s 3c", __func__); + return true; + default: + pr_info("No method to get for fan_speed_unit %d.", + fancurve->fan_speed_unit); + return false; + } + return false; } // TODO: remove { ... } from single line if body @@ -2263,16 +2331,27 @@ static ssize_t fancurve_print_seqfile(const struct fancurve *fancurve, { int i; + seq_printf(s, "Fan curve current point id: %ld\n", + fancurve->current_point_i); + seq_printf(s, "Fan curve points size: %ld\n", fancurve->size); + seq_printf( s, - "rpm1|rpm2|acceleration|deceleration|cpu_min_temp|cpu_max_temp|gpu_min_temp|gpu_max_temp|ic_min_temp|ic_max_temp\n"); + "u(speed_of_unit)|speed1[u]|speed2[u]|speed1[pwm]|speed2[pwm]|acceleration|deceleration|cpu_min_temp|cpu_max_temp|gpu_min_temp|gpu_max_temp|ic_min_temp|ic_max_temp\n"); for (i = 0; i < fancurve->size; ++i) { + int speed_pwm1 = -1; + int speed_pwm2 = -1; const struct fancurve_point *point = &fancurve->points[i]; + fancurve_get_speed_pwm(fancurve, i, 0, &speed_pwm1); + fancurve_get_speed_pwm(fancurve, i, 0, &speed_pwm2); + seq_printf( - s, "%d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\n", - point->rpm1_raw * 100, point->rpm2_raw * 100, - point->accel, point->decel, point->cpu_min_temp_celsius, + s, + "%d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\n", + fancurve->fan_speed_unit, point->speed1, point->speed2, + speed_pwm1, speed_pwm2, point->accel, point->decel, + point->cpu_min_temp_celsius, point->cpu_max_temp_celsius, point->gpu_min_temp_celsius, point->gpu_max_temp_celsius, point->ic_min_temp_celsius, @@ -2807,17 +2886,18 @@ static ssize_t wmi_read_fancurve_custom(const struct model_config *model, (struct WMIFanTableRead *)&buffer[0]; fancurve->current_point_i = 0; fancurve->size = 10; - fancurve->points[0].rpm1_raw = fantable->FSS0; - fancurve->points[1].rpm1_raw = fantable->FSS1; - fancurve->points[2].rpm1_raw = fantable->FSS2; - fancurve->points[3].rpm1_raw = fantable->FSS3; - fancurve->points[4].rpm1_raw = fantable->FSS4; - fancurve->points[5].rpm1_raw = fantable->FSS5; - fancurve->points[6].rpm1_raw = fantable->FSS6; - fancurve->points[7].rpm1_raw = fantable->FSS7; - fancurve->points[8].rpm1_raw = fantable->FSS8; - fancurve->points[9].rpm1_raw = fantable->FSS9; - //fancurve->points[10].rpm1_raw = fantable->FSSA; + fancurve->fan_speed_unit = FAN_SPEED_UNIT_PERCENT; + fancurve->points[0].speed1 = fantable->FSS0; + fancurve->points[1].speed1 = fantable->FSS1; + fancurve->points[2].speed1 = fantable->FSS2; + fancurve->points[3].speed1 = fantable->FSS3; + fancurve->points[4].speed1 = fantable->FSS4; + fancurve->points[5].speed1 = fantable->FSS5; + fancurve->points[6].speed1 = fantable->FSS6; + fancurve->points[7].speed1 = fantable->FSS7; + fancurve->points[8].speed1 = fantable->FSS8; + fancurve->points[9].speed1 = fantable->FSS9; + //fancurve->points[10].speed1 = fantable->FSSA; } return err; } @@ -2845,16 +2925,16 @@ static ssize_t wmi_write_fancurve_custom(const struct model_config *model, // CreateByteField (Arg2, 0x18, FSS9) memset(buffer, 0, sizeof(buffer)); - buffer[0x06] = fancurve->points[0].rpm1_raw; - buffer[0x08] = fancurve->points[1].rpm1_raw; - buffer[0x0A] = fancurve->points[2].rpm1_raw; - buffer[0x0C] = fancurve->points[3].rpm1_raw; - buffer[0x0E] = fancurve->points[4].rpm1_raw; - buffer[0x10] = fancurve->points[5].rpm1_raw; - buffer[0x12] = fancurve->points[6].rpm1_raw; - buffer[0x14] = fancurve->points[7].rpm1_raw; - buffer[0x16] = fancurve->points[8].rpm1_raw; - buffer[0x18] = fancurve->points[9].rpm1_raw; + buffer[0x06] = fancurve->points[0].speed1; + buffer[0x08] = fancurve->points[1].speed1; + buffer[0x0A] = fancurve->points[2].speed1; + buffer[0x0C] = fancurve->points[3].speed1; + buffer[0x0E] = fancurve->points[4].speed1; + buffer[0x10] = fancurve->points[5].speed1; + buffer[0x12] = fancurve->points[6].speed1; + buffer[0x14] = fancurve->points[7].speed1; + buffer[0x16] = fancurve->points[8].speed1; + buffer[0x18] = fancurve->points[9].speed1; print_hex_dump(KERN_INFO, "legion_laptop fan table wmi write buffer", DUMP_PREFIX_ADDRESS, 16, 1, buffer, sizeof(buffer), @@ -2879,12 +2959,13 @@ static int ec_read_fancurve_legion(struct ecram *ecram, { size_t i = 0; + fancurve->fan_speed_unit = FAN_SPEED_UNIT_RPM_HUNDRED; for (i = 0; i < MAXFANCURVESIZE; ++i) { struct fancurve_point *point = &fancurve->points[i]; - point->rpm1_raw = + point->speed1 = ecram_read(ecram, model->registers->EXT_FAN1_BASE + i); - point->rpm2_raw = + point->speed2 = ecram_read(ecram, model->registers->EXT_FAN2_BASE + i); point->accel = ecram_read( @@ -2936,9 +3017,9 @@ static int ec_write_fancurve_legion(struct ecram *ecram, &fancurve_point_zero; ecram_write(ecram, model->registers->EXT_FAN1_BASE + i, - point->rpm1_raw); + point->speed1); ecram_write(ecram, model->registers->EXT_FAN2_BASE + i, - point->rpm2_raw); + point->speed2); ecram_write(ecram, model->registers->EXT_FAN_ACC_BASE + i, point->accel); @@ -2985,12 +3066,13 @@ static int ec_read_fancurve_ideapad(struct ecram *ecram, { size_t i = 0; + fancurve->fan_speed_unit = FAN_SPEED_UNIT_RPM_HUNDRED; for (i = 0; i < FANCURVESIZE_IDEAPDAD; ++i) { struct fancurve_point *point = &fancurve->points[i]; - point->rpm1_raw = + point->speed1 = ecram_read(ecram, model->registers->EXT_FAN1_BASE + i); - point->rpm2_raw = + point->speed2 = ecram_read(ecram, model->registers->EXT_FAN2_BASE + i); point->accel = 0; @@ -3035,14 +3117,14 @@ static int ec_write_fancurve_ideapad(struct ecram *ecram, const struct fancurve_point *point = &fancurve->points[i]; ecram_write(ecram, model->registers->EXT_FAN1_BASE + i, - point->rpm1_raw); + point->speed1); valr1 = ecram_read(ecram, model->registers->EXT_FAN1_BASE + i); ecram_write(ecram, model->registers->EXT_FAN2_BASE + i, - point->rpm2_raw); + point->speed2); valr2 = ecram_read(ecram, model->registers->EXT_FAN2_BASE + i); - pr_info("Writing fan1: %d; reading fan1: %d\n", point->rpm1_raw, + pr_info("Writing fan1: %d; reading fan1: %d\n", point->speed1, valr1); - pr_info("Writing fan2: %d; reading fan2: %d\n", point->rpm2_raw, + pr_info("Writing fan2: %d; reading fan2: %d\n", point->speed2, valr2); // write to memory and repeat 8 bytes later again @@ -3086,26 +3168,31 @@ static int ec_write_fancurve_ideapad(struct ecram *ecram, #define FANCURVESIZE_LOQ 10 static int ec_read_fancurve_loq(struct ecram *ecram, - const struct model_config *model, - struct fancurve *fancurve) + const struct model_config *model, + struct fancurve *fancurve) { size_t i = 0; size_t struct_offset = 3; // {cpu_temp: u8, rpm: u8, gpu_temp?: u8} + fancurve->fan_speed_unit = FAN_SPEED_UNIT_RPM_HUNDRED; for (i = 0; i < FANCURVESIZE_LOQ; ++i) { struct fancurve_point *point = &fancurve->points[i]; - point->rpm1_raw = - ecram_read(ecram, model->registers->EXT_FAN1_BASE + (i * struct_offset)); - point->rpm2_raw = - ecram_read(ecram, model->registers->EXT_FAN2_BASE + (i * struct_offset)); + point->speed1 = + ecram_read(ecram, model->registers->EXT_FAN1_BASE + + (i * struct_offset)); + point->speed2 = + ecram_read(ecram, model->registers->EXT_FAN2_BASE + + (i * struct_offset)); point->accel = 0; point->decel = 0; point->cpu_max_temp_celsius = - ecram_read(ecram, model->registers->EXT_CPU_TEMP + (i * struct_offset)); + ecram_read(ecram, model->registers->EXT_CPU_TEMP + + (i * struct_offset)); point->gpu_max_temp_celsius = - ecram_read(ecram, model->registers->EXT_GPU_TEMP + (i * struct_offset)); + ecram_read(ecram, model->registers->EXT_GPU_TEMP + + (i * struct_offset)); point->cpu_min_temp_celsius = 0; point->gpu_min_temp_celsius = 0; point->ic_max_temp_celsius = 0; @@ -3121,8 +3208,8 @@ static int ec_read_fancurve_loq(struct ecram *ecram, } static int ec_write_fancurve_loq(struct ecram *ecram, - const struct model_config *model, - const struct fancurve *fancurve) + const struct model_config *model, + const struct fancurve *fancurve) { size_t i; int valr1; @@ -3132,22 +3219,32 @@ static int ec_write_fancurve_loq(struct ecram *ecram, for (i = 0; i < FANCURVESIZE_LOQ; ++i) { const struct fancurve_point *point = &fancurve->points[i]; - ecram_write(ecram, model->registers->EXT_FAN1_BASE + (i * struct_offset), - point->rpm1_raw); - valr1 = ecram_read(ecram, model->registers->EXT_FAN1_BASE + (i * struct_offset)); - ecram_write(ecram, model->registers->EXT_FAN2_BASE + (i * struct_offset), - point->rpm2_raw); - valr2 = ecram_read(ecram, model->registers->EXT_FAN2_BASE + (i * struct_offset)); - pr_info("Writing fan1: %d; reading fan1: %d\n", point->rpm1_raw, + ecram_write(ecram, + model->registers->EXT_FAN1_BASE + + (i * struct_offset), + point->speed1); + valr1 = ecram_read(ecram, model->registers->EXT_FAN1_BASE + + (i * struct_offset)); + ecram_write(ecram, + model->registers->EXT_FAN2_BASE + + (i * struct_offset), + point->speed2); + valr2 = ecram_read(ecram, model->registers->EXT_FAN2_BASE + + (i * struct_offset)); + pr_info("Writing fan1: %d; reading fan1: %d\n", point->speed1, valr1); - pr_info("Writing fan2: %d; reading fan2: %d\n", point->rpm2_raw, + pr_info("Writing fan2: %d; reading fan2: %d\n", point->speed2, valr2); // write to memory and repeat 8 bytes later again - ecram_write(ecram, model->registers->EXT_CPU_TEMP + (i * struct_offset), + ecram_write(ecram, + model->registers->EXT_CPU_TEMP + + (i * struct_offset), point->cpu_max_temp_celsius); // write to memory and repeat 8 bytes later again - ecram_write(ecram, model->registers->EXT_GPU_TEMP + (i * struct_offset), + ecram_write(ecram, + model->registers->EXT_GPU_TEMP + + (i * struct_offset), point->gpu_max_temp_celsius); } @@ -3157,6 +3254,7 @@ static int ec_write_fancurve_loq(struct ecram *ecram, static int read_fancurve(struct legion_private *priv, struct fancurve *fancurve) { // TODO: use enums or function pointers? + pr_info("Reading fancurve"); // TODO: remove that switch (priv->conf->access_method_fancurve) { case ACCESS_METHOD_EC: return ec_read_fancurve_legion(&priv->ecram, priv->conf, @@ -3165,8 +3263,7 @@ static int read_fancurve(struct legion_private *priv, struct fancurve *fancurve) return ec_read_fancurve_ideapad(&priv->ecram, priv->conf, fancurve); case ACCESS_METHOD_EC3: - return ec_read_fancurve_loq(&priv->ecram, priv->conf, - fancurve); + return ec_read_fancurve_loq(&priv->ecram, priv->conf, fancurve); case ACCESS_METHOD_WMI3: return wmi_read_fancurve_custom(priv->conf, fancurve); default: @@ -3189,7 +3286,7 @@ static int write_fancurve(struct legion_private *priv, fancurve); case ACCESS_METHOD_EC3: return ec_write_fancurve_loq(&priv->ecram, priv->conf, - fancurve); + fancurve); case ACCESS_METHOD_WMI3: return wmi_write_fancurve_custom(priv->conf, fancurve); default: @@ -3380,7 +3477,8 @@ static enum legion_wmi_powermode ec_to_wmi_powermode(int ec_mode) } } -static enum legion_ec_powermode wmi_to_ec_powermode(enum legion_wmi_powermode wmi_mode) +static enum legion_ec_powermode +wmi_to_ec_powermode(enum legion_wmi_powermode wmi_mode) { switch (wmi_mode) { case LEGION_WMI_POWERMODE_QUIET: @@ -3833,11 +3931,9 @@ static int debugfs_fancurve_show(struct seq_file *s, void *unused) &is_maximumfanspeed); seq_file_print_with_error(s, "fanfullspeed EC", err, is_maximumfanspeed); + seq_printf(s, "Max speed for fancurve: %d\n", MAX_RPM); read_fancurve(priv, &priv->fancurve); - seq_printf(s, "EC fan curve current point id: %ld\n", - priv->fancurve.current_point_i); - seq_printf(s, "EC fan curve points size: %ld\n", priv->fancurve.size); seq_puts(s, "Current fan curve in hardware:\n"); fancurve_print_seqfile(&priv->fancurve, s); @@ -5005,6 +5101,12 @@ static struct attribute *sensor_hwmon_attributes[] = { NULL }; +static ssize_t fan_max_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "%d\n", MAX_RPM); +} + static ssize_t autopoint_show(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -5014,11 +5116,20 @@ static ssize_t autopoint_show(struct device *dev, struct legion_private *priv = dev_get_drvdata(dev); int fancurve_attr_id = to_sensor_dev_attr_2(devattr)->nr; int point_id = to_sensor_dev_attr_2(devattr)->index; + bool ok = true; + + pr_info("%s 1 point id=%d, fancurve_attr_id id=%d, fancurve.fan_speed_unit=%d, fancurve.size=%ld", + __func__, point_id, fancurve_attr_id, + fancurve.fan_speed_unit, fancurve.size); mutex_lock(&priv->fancurve_mutex); err = read_fancurve(priv, &fancurve); mutex_unlock(&priv->fancurve_mutex); + pr_info("%s 2 point id=%d, fancurve_attr_id id=%d, err=%d, fancurve.fan_speed_unit=%d, fancurve.size=%ld", + __func__, point_id, fancurve_attr_id, err, + fancurve.fan_speed_unit, fancurve.size); + if (err) { pr_info("Failed to read fancurve\n"); return -EOPNOTSUPP; @@ -5031,10 +5142,16 @@ static ssize_t autopoint_show(struct device *dev, switch (fancurve_attr_id) { case FANCURVE_ATTR_PWM1: - value = fancurve.points[point_id].rpm1_raw * 100; + pr_info("%s ->3a pwm1 point id=%d, fancurve_attr_id id=%d", + __func__, point_id, fancurve_attr_id); + ok = fancurve_get_speed_pwm(&fancurve, point_id, 0, &value); + pr_info("%s ok: %d->3a2", __func__, ok); break; case FANCURVE_ATTR_PWM2: - value = fancurve.points[point_id].rpm2_raw * 100; + pr_info("%s ->3b pwm2 point id=%d, fancurve_attr_id id=%d", + __func__, point_id, fancurve_attr_id); + ok = fancurve_get_speed_pwm(&fancurve, point_id, 1, &value); + pr_info("%s ok: %d->3b2", __func__, ok); break; case FANCURVE_ATTR_CPU_TEMP: value = fancurve.points[point_id].cpu_max_temp_celsius; @@ -5068,7 +5185,11 @@ static ssize_t autopoint_show(struct device *dev, fancurve_attr_id); return -EOPNOTSUPP; } - + if (!ok) { + pr_info("%s 4a: error!", __func__); + value = 0; + } + pr_info("%s 4b XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", __func__); return sprintf(buf, "%d\n", value); } @@ -5110,10 +5231,10 @@ static ssize_t autopoint_store(struct device *dev, switch (fancurve_attr_id) { case FANCURVE_ATTR_PWM1: - valid = fancurve_set_rpm1(&fancurve, point_id, value); + valid = fancurve_set_speed_pwm(&fancurve, point_id, 0, value); break; case FANCURVE_ATTR_PWM2: - valid = fancurve_set_rpm2(&fancurve, point_id, value); + valid = fancurve_set_speed_pwm(&fancurve, point_id, 1, value); break; case FANCURVE_ATTR_CPU_TEMP: valid = fancurve_set_cpu_temp_max(&fancurve, point_id, value); @@ -5174,7 +5295,8 @@ static ssize_t autopoint_store(struct device *dev, return count; } -// rpm1 +// pwm1 +static SENSOR_DEVICE_ATTR_RO(fan1_max, fan_max, 0); static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point1_pwm, autopoint, FANCURVE_ATTR_PWM1, 0); static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point2_pwm, autopoint, @@ -5195,7 +5317,8 @@ static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point9_pwm, autopoint, FANCURVE_ATTR_PWM1, 8); static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point10_pwm, autopoint, FANCURVE_ATTR_PWM1, 9); -// rpm2 +// pwm2 +static SENSOR_DEVICE_ATTR_RO(fan2_max, fan_max, 0); static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point1_pwm, autopoint, FANCURVE_ATTR_PWM2, 0); static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point2_pwm, autopoint, @@ -5420,8 +5543,7 @@ static ssize_t minifancurve_store(struct device *dev, err = kstrtoint(buf, 0, &value); if (err) { err = -1; - pr_info("Parsing hwmon store failed: error:%d\n", - err); + pr_info("Parsing hwmon store failed: error:%d\n", err); goto error; } @@ -5478,8 +5600,7 @@ static ssize_t pwm1_mode_store(struct device *dev, err = kstrtoint(buf, 0, &value); if (err) { err = -1; - pr_info("Parsing hwmon store failed: error:%d\n", - err); + pr_info("Parsing hwmon store failed: error:%d\n", err); goto error; } is_maximumfanspeed = value == 0; @@ -5504,6 +5625,8 @@ static ssize_t pwm1_mode_store(struct device *dev, static SENSOR_DEVICE_ATTR_RW(pwm1_mode, pwm1_mode, 0); static struct attribute *fancurve_hwmon_attributes[] = { + &sensor_dev_attr_fan1_max.dev_attr.attr, + &sensor_dev_attr_fan2_max.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, diff --git a/python/legion_linux/legion_linux/legion.py b/python/legion_linux/legion_linux/legion.py index 906ac475..51c3969a 100755 --- a/python/legion_linux/legion_linux/legion.py +++ b/python/legion_linux/legion_linux/legion.py @@ -42,8 +42,8 @@ def get_dmesg(only_tail=False, filter_log=True): @dataclass(order=True) class FanCurveEntry: - fan1_speed: int - fan2_speed: int + fan1_speed: float # fan speed in rpm + fan2_speed: float # fan speed in rpm cpu_lower_temp: int cpu_upper_temp: int gpu_lower_temp: int @@ -165,11 +165,9 @@ def _notify(self): for func in self.callbacks: func(self) - # pylint: disable=no-self-use def exists(self): return True - # pylint: disable=no-self-use def get_values(self) -> List[NamedValue]: return [] @@ -299,7 +297,6 @@ def _find_by_file_pattern(pattern): return matches[0] return None - # pylint: disable=no-self-use def get_values(self) -> List[NamedValue]: return [] @@ -667,7 +664,6 @@ def _exec_cmd(self, cmd, timeout=None) -> Tuple[str, int]: def name(self): return type(self).__name__ - # pylint: disable=no-self-use def get_values(self) -> List[NamedValue]: return [] @@ -743,6 +739,8 @@ class FanCurveIO(Feature): pwm1_accel = "pwm1_auto_point{}_accel" pwm1_decel = "pwm1_auto_point{}_decel" minifancurve = "minifancurve" + fan1_max = "fan1_max" + fan2_max = "fan2_max" encoding = DEFAULT_ENCODING @@ -750,7 +748,7 @@ def __init__(self, expect_hwmon=True): super().__init__() self.hwmon_path = self._find_hwmon_dir() if (not self.hwmon_path) and expect_hwmon: - raise Exception("hwmon dir not found") + raise FileNotFoundError("hwmon dir not found") def exists(self): if self.hwmon_path is not None: @@ -792,16 +790,30 @@ def _write_file_or(file_path, value): if os.path.exists(file_path): FanCurveIO._write_file(file_path, value) - def set_fan_1_speed(self, point_id, value): + def get_fan_1_max_rpm(self): + file_path = self.hwmon_path + self.fan1_max + return int(self._read_file(file_path)) + + def get_fan_2_max_rpm(self): + file_path = self.hwmon_path + self.fan2_max + return int(self._read_file(file_path)) + + def set_fan_1_speed_pwm(self, point_id, value): point_id = self._validate_point_id(point_id) file_path = self.hwmon_path + self.pwm1_fan_speed.format(point_id) self._write_file(file_path, value) - def set_fan_2_speed(self, point_id, value): + def set_fan_2_speed_pwm(self, point_id, value): point_id = self._validate_point_id(point_id) file_path = self.hwmon_path + self.pwm2_fan_speed.format(point_id) self._write_file(file_path, value) + def set_fan_1_speed_rpm(self, point_id, value): + return self.set_fan_1_speed_pwm(point_id, round(value/self.get_fan_1_max_rpm()*255.0)) + + def set_fan_2_speed_rpm(self, point_id, value): + return self.set_fan_2_speed_pwm(point_id, round(value/self.get_fan_2_max_rpm()*255.0)) + def set_lower_cpu_temperature(self, point_id, value): point_id = self._validate_point_id(point_id) file_path = self.hwmon_path + self.pwm1_temp_hyst.format(point_id) @@ -842,16 +854,22 @@ def set_deceleration(self, point_id, value): file_path = self.hwmon_path + self.pwm1_decel.format(point_id) self._write_file(file_path, value) - def get_fan_1_speed(self, point_id): + def get_fan_1_speed_pwm(self, point_id): point_id = self._validate_point_id(point_id) file_path = self.hwmon_path + self.pwm1_fan_speed.format(point_id) return self._read_file(file_path) - def get_fan_2_speed(self, point_id): + def get_fan_2_speed_pwm(self, point_id): point_id = self._validate_point_id(point_id) file_path = self.hwmon_path + self.pwm2_fan_speed.format(point_id) return self._read_file(file_path) + def get_fan_1_speed_rpm(self, point_id): + return round(self.get_fan_1_speed_pwm(point_id)/255.0*self.get_fan_1_max_rpm(), ndigits=2) + + def get_fan_2_speed_rpm(self, point_id): + return round(self.get_fan_2_speed_pwm(point_id)/255.0*self.get_fan_2_max_rpm(), ndigits=2) + def get_lower_cpu_temperature(self, point_id): point_id = self._validate_point_id(point_id) file_path = self.hwmon_path + self.pwm1_temp_hyst.format(point_id) @@ -924,8 +942,8 @@ def write_fan_curve(self, fan_curve: FanCurve, _=False): log.error(str(error)) for index, entry in enumerate(fan_curve.entries): point_id = index + 1 - self.set_fan_1_speed(point_id, entry.fan1_speed) - self.set_fan_2_speed(point_id, entry.fan2_speed) + self.set_fan_1_speed_rpm(point_id, entry.fan1_speed) + self.set_fan_2_speed_rpm(point_id, entry.fan2_speed) self.set_lower_cpu_temperature(point_id, entry.cpu_lower_temp) self.set_upper_cpu_temperature(point_id, entry.cpu_upper_temp) self.set_lower_gpu_temperature(point_id, entry.gpu_lower_temp) @@ -939,8 +957,8 @@ def read_fan_curve(self) -> FanCurve: """Reads a fan curve object from the file system""" entries = [] for point_id in range(1, 11): - fan1_speed = self.get_fan_1_speed(point_id) - fan2_speed = self.get_fan_2_speed(point_id) + fan1_speed = self.get_fan_1_speed_rpm(point_id) + fan2_speed = self.get_fan_2_speed_rpm(point_id) cpu_lower_temp = self.get_lower_cpu_temperature(point_id) cpu_upper_temp = self.get_upper_cpu_temperature(point_id) gpu_lower_temp = self.get_lower_gpu_temperature(point_id) @@ -1028,7 +1046,6 @@ def get_settings(self) -> Settings: settings.setting_entries[name] = value return settings - # pylint: disable=no-self-use def apply_settings(self, preset: Settings): for name, value in preset.setting_entries.items(): log.error("Try seting %s from preset to %s", name, value) diff --git a/python/legion_linux/legion_linux/legion_cli.py b/python/legion_linux/legion_linux/legion_cli.py index c0c6dc87..655de67a 100755 --- a/python/legion_linux/legion_linux/legion_cli.py +++ b/python/legion_linux/legion_linux/legion_cli.py @@ -66,19 +66,15 @@ def command_disable_cli(self, **_) -> int: return self.command_disable() return -10 - # pylint: disable=no-self-use def exists(self) -> bool: return False - # pylint: disable=no-self-use def command_status(self, **_) -> int: return 0 - # pylint: disable=no-self-use def command_enable(self, **_) -> int: return -1 - # pylint: disable=no-self-use def command_disable(self, **_) -> int: return -1 diff --git a/python/legion_linux/legion_linux/legion_gui.py b/python/legion_linux/legion_linux/legion_gui.py index 227f4dfb..c107fc76 100755 --- a/python/legion_linux/legion_linux/legion_gui.py +++ b/python/legion_linux/legion_linux/legion_gui.py @@ -977,8 +977,8 @@ def set_disabled(self, value: bool): self.decel_edit.setDisabled(value) def get(self) -> FanCurveEntry: - fan1_speed = int(self.fan_speed1_edit.text()) - fan2_speed = int(self.fan_speed2_edit.text()) + fan1_speed = float(self.fan_speed1_edit.text()) + fan2_speed = float(self.fan_speed2_edit.text()) cpu_lower_temp = int(self.cpu_lower_temp_edit.text()) cpu_upper_temp = int(self.cpu_upper_temp_edit.text()) gpu_lower_temp = int(self.gpu_lower_temp_edit.text())