From 8770d88bc080b84767ad3e9c434849f0fb736114 Mon Sep 17 00:00:00 2001 From: teackot Date: Thu, 5 Jan 2023 00:45:03 +0300 Subject: [PATCH 01/28] Created a struct to store different configurations for different fw versions. Implemented for power_supply and root. --- constants.h | 170 +++++++++++++++++++++++++++++ msi-ec.c | 305 +++++++++++++++++++++++++++++++++------------------- 2 files changed, 367 insertions(+), 108 deletions(-) diff --git a/constants.h b/constants.h index 6bfc3d0..74c5bbe 100644 --- a/constants.h +++ b/constants.h @@ -1,6 +1,8 @@ #ifndef __MSI_EC_CONSTANTS__ #define __MSI_EC_CONSTANTS__ +#include + #define MSI_DRIVER_NAME "msi-ec" #define MSI_EC_WEBCAM_ADDRESS 0x2e #define MSI_EC_WEBCAM_ON 0x4a @@ -72,4 +74,172 @@ static int MSI_EC_KBD_BL_STATE[4] = { #define MSI_EC_CAMERA_STATE_OFF 0x80 #define MSI_EC_CAMERA_STATE_ON 0x84 +struct msi_ec_fn_win_swap_conf { + int address; + int fn_left_value; + int fn_right_value; +}; + +struct msi_ec_battery_mode_conf { + int address; + int modes[3]; // min, mid, max +}; + +struct msi_ec_power_status_conf { + int address; + int lid_open_bit; + int ac_connected_bit; +}; + +struct msi_ec_charge_conf { + int battery_charge_address; + int charging_status_address; +}; + +struct msi_ec_cooler_boost_conf { + int address; + u8 on_value; + u8 off_value; +}; + +struct msi_ec_shift_mode_conf { + int address; + int off_value; + int base_value; + int max_mode; +}; + +#define MSI_EC_FW_VERSION_LENGTH 12 +#define MSI_EC_FW_DATE_LENGTH 8 +#define MSI_EC_FW_TIME_LENGTH 8 + +struct msi_ec_fw_conf { + int version_address; + int date_address; + int time_address; +}; + +struct msi_ec_charge_control_conf { + int address; + int offset_start; + int offset_end; + int range_min; + int range_max; +}; + +struct msi_ec_cpu_conf { + int rt_temp_address; + int rt_fan_speed_address; // realtime + int rt_fan_speed_base_min; + int rt_fan_speed_base_max; + int bs_fan_speed_address; // basic + int bs_fan_speed_base_min; + int bs_fan_speed_base_max; +}; + +struct msi_ec_gpu_conf { + int rt_temp_address; + int rt_fan_speed_address; // realtime +}; + +struct msi_ec_fan_mode_conf { + int address; + int mode_values[4]; + int max_mode; +}; + +struct msi_ec_led_conf { + int mic_mute_led_address; + int mute_led_address; + int base_value; + int bit; +}; + +struct msi_ec_kbd_bl_conf { + int bl_mode_address; + int bl_modes[2]; + int max_mode; + + int bl_state_address; + int state_base_value; + int max_state; +}; + +struct msi_ec_webcam_conf { + int address; + int hard_address; + u8 on_value; + u8 off_value; +}; + +struct msi_ec_conf { + struct msi_ec_fn_win_swap_conf fn_win_swap; + struct msi_ec_battery_mode_conf battery_mode; + struct msi_ec_power_status_conf power_status; + struct msi_ec_charge_conf charge; + struct msi_ec_cooler_boost_conf cooler_boost; + struct msi_ec_shift_mode_conf shift_mode; + struct msi_ec_fw_conf fw; + struct msi_ec_charge_control_conf charge_control; + struct msi_ec_cpu_conf cpu; + struct msi_ec_gpu_conf gpu; + struct msi_ec_fan_mode_conf fan_mode; + struct msi_ec_led_conf leds; + struct msi_ec_kbd_bl_conf kbd_bl; + struct msi_ec_webcam_conf webcam; +}; + +static struct msi_ec_conf CONFIGURATIONS[1] = { + { + .fn_win_swap = { 0xbf, 0x40, 0x50 }, + .battery_mode = { 0xef, { 0xbc, 0xd0, 0xe4 } }, + .power_status = { 0x30, 1, 0 }, + .charge = { 0x42, 0x31 }, + .cooler_boost = { 0x98, 0x82, 0x02 }, + .shift_mode = { 0xf2, 0x80, 0xc0, 4 }, + .fw = { 0xa0, 0xac, 0xb4 }, + .charge_control = { 0xef, 0x8a, 0x80, 0x8a, 0xe4 }, + .cpu = { + .rt_temp_address = 0x68, + .rt_fan_speed_address = 0x71, + .rt_fan_speed_base_min = 0x19, + .rt_fan_speed_base_max = 0x37, + .bs_fan_speed_address = 0x89, + .bs_fan_speed_base_min = 0x00, + .bs_fan_speed_base_max = 0x0f, + }, + .gpu = { + .rt_temp_address = 0x80, + .rt_fan_speed_address = 0x89, + }, + .fan_mode = { + .address = 0xf4, + .mode_values = { 0x0d, 0x1d, 0x4d, 0x8d }, + .max_mode = 3, + }, + .leds = { + .mic_mute_led_address = 0x2b, + .mute_led_address = 0x2c, + .base_value = 0x80, + .bit = 2, + }, + .kbd_bl = { + .bl_mode_address = 0x2c, // ? + .bl_modes = { 0x00, 0x08 }, // ? + .max_mode = 1, // ? + .bl_state_address = 0xf3, + .state_base_value = 0x80, + .max_state = 3, + }, + .webcam = { + .address = 0x2e, + .hard_address = 0x2f, + .on_value = 0x84, + .off_value = 0x80, + }, + }, +}; + +static struct msi_ec_conf *conf = CONFIGURATIONS + 0; // current configuration + #endif // __MSI_EC_CONSTANTS__ diff --git a/msi-ec.c b/msi-ec.c index fcd706f..5fbd03f 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -67,7 +67,7 @@ static ssize_t charge_control_threshold_show(u8 offset, struct device *device, u8 rdata; int result; - result = ec_read(MSI_EC_CHARGE_CONTROL_ADDRESS, &rdata); + result = ec_read(conf->charge_control.address, &rdata); if (result < 0) return result; @@ -78,7 +78,7 @@ static ssize_t charge_control_start_threshold_show(struct device *device, struct device_attribute *attr, char *buf) { - return charge_control_threshold_show(MSI_EC_CHARGE_CONTROL_OFFSET_START, + return charge_control_threshold_show(conf->charge_control.offset_start, device, attr, buf); } @@ -86,7 +86,7 @@ static ssize_t charge_control_end_threshold_show(struct device *device, struct device_attribute *attr, char *buf) { - return charge_control_threshold_show(MSI_EC_CHARGE_CONTROL_OFFSET_END, + return charge_control_threshold_show(conf->charge_control.offset_end, device, attr, buf); } @@ -102,11 +102,11 @@ static ssize_t charge_control_threshold_store(u8 offset, struct device *dev, return result; wdata += offset; - if (wdata < MSI_EC_CHARGE_CONTROL_RANGE_MIN || - wdata > MSI_EC_CHARGE_CONTROL_RANGE_MAX) + if (wdata < conf->charge_control.range_min || + wdata > conf->charge_control.range_max) return -EINVAL; - result = ec_write(MSI_EC_CHARGE_CONTROL_ADDRESS, wdata); + result = ec_write(conf->charge_control.address, wdata); if (result < 0) return result; @@ -119,14 +119,14 @@ charge_control_start_threshold_store(struct device *dev, const char *buf, size_t count) { return charge_control_threshold_store( - MSI_EC_CHARGE_CONTROL_OFFSET_START, dev, attr, buf, count); + conf->charge_control.offset_start, dev, attr, buf, count); } static ssize_t charge_control_end_threshold_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - return charge_control_threshold_store(MSI_EC_CHARGE_CONTROL_OFFSET_END, + return charge_control_threshold_store(conf->charge_control.offset_end, dev, attr, buf, count); } @@ -170,18 +170,26 @@ static ssize_t webcam_show(struct device *device, struct device_attribute *attr, u8 rdata; int result; - result = ec_read(MSI_EC_WEBCAM_ADDRESS, &rdata); + result = ec_read(conf->webcam.address, &rdata); if (result < 0) return result; - switch (rdata) { - case MSI_EC_WEBCAM_ON: + if (rdata == conf->webcam.on_value) { return sprintf(buf, "%s\n", "on"); - case MSI_EC_WEBCAM_OFF: + } else if (rdata == conf->webcam.off_value) { return sprintf(buf, "%s\n", "off"); - default: + } else { return sprintf(buf, "%s (%i)\n", "unknown", rdata); } + +// switch (rdata) { +// case conf->webcam.on_value: +// return sprintf(buf, "%s\n", "on"); +// case conf->webcam.off_value: +// return sprintf(buf, "%s\n", "off"); +// default: +// return sprintf(buf, "%s (%i)\n", "unknown", rdata); +// } } static ssize_t webcam_store(struct device *dev, struct device_attribute *attr, @@ -190,10 +198,10 @@ static ssize_t webcam_store(struct device *dev, struct device_attribute *attr, int result = -EINVAL; if (streq(buf, "on")) - result = ec_write(MSI_EC_WEBCAM_ADDRESS, MSI_EC_WEBCAM_ON); + result = ec_write(conf->webcam.address, conf->webcam.on_value); if (streq(buf, "off")) - result = ec_write(MSI_EC_WEBCAM_ADDRESS, MSI_EC_WEBCAM_OFF); + result = ec_write(conf->webcam.address, conf->webcam.off_value); if (result < 0) return result; @@ -207,18 +215,26 @@ static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, u8 rdata; int result; - result = ec_read(MSI_EC_FN_WIN_ADDRESS, &rdata); + result = ec_read(conf->fn_win_swap.address, &rdata); if (result < 0) return result; - switch (rdata) { - case MSI_EC_FN_KEY_LEFT: + if (rdata == conf->fn_win_swap.fn_left_value) { return sprintf(buf, "%s\n", "left"); - case MSI_EC_FN_KEY_RIGHT: + } else if (rdata == conf->fn_win_swap.fn_right_value) { return sprintf(buf, "%s\n", "right"); - default: + } else { return sprintf(buf, "%s (%i)\n", "unknown", rdata); } + +// switch (rdata) { +// case conf->fn_win_swap.fn_left_value: +// return sprintf(buf, "%s\n", "left"); +// case conf->fn_win_swap.fn_right_value: +// return sprintf(buf, "%s\n", "right"); +// default: +// return sprintf(buf, "%s (%i)\n", "unknown", rdata); +// } } static ssize_t fn_key_store(struct device *dev, struct device_attribute *attr, @@ -227,10 +243,10 @@ static ssize_t fn_key_store(struct device *dev, struct device_attribute *attr, int result = -EINVAL; if (streq(buf, "left")) - result = ec_write(MSI_EC_FN_WIN_ADDRESS, MSI_EC_FN_KEY_LEFT); + result = ec_write(conf->fn_win_swap.address, conf->fn_win_swap.fn_left_value); if (streq(buf, "right")) - result = ec_write(MSI_EC_FN_WIN_ADDRESS, MSI_EC_FN_KEY_RIGHT); + result = ec_write(conf->fn_win_swap.address, conf->fn_win_swap.fn_right_value); if (result < 0) return result; @@ -244,18 +260,26 @@ static ssize_t win_key_show(struct device *device, u8 rdata; int result; - result = ec_read(MSI_EC_FN_WIN_ADDRESS, &rdata); + result = ec_read(conf->fn_win_swap.address, &rdata); if (result < 0) return result; - switch (rdata) { - case MSI_EC_WIN_KEY_LEFT: + if (rdata == conf->fn_win_swap.fn_right_value) { return sprintf(buf, "%s\n", "left"); - case MSI_EC_WIN_KEY_RIGHT: + } else if (rdata == conf->fn_win_swap.fn_left_value) { return sprintf(buf, "%s\n", "right"); - default: + } else { return sprintf(buf, "%s (%i)\n", "unknown", rdata); } + +// switch (rdata) { +// case conf->fn_win_swap.fn_right_value: +// return sprintf(buf, "%s\n", "left"); +// case conf->fn_win_swap.fn_left_value: +// return sprintf(buf, "%s\n", "right"); +// default: +// return sprintf(buf, "%s (%i)\n", "unknown", rdata); +// } } static ssize_t win_key_store(struct device *dev, struct device_attribute *attr, @@ -264,10 +288,10 @@ static ssize_t win_key_store(struct device *dev, struct device_attribute *attr, int result = -EINVAL; if (streq(buf, "left")) - result = ec_write(MSI_EC_FN_WIN_ADDRESS, MSI_EC_WIN_KEY_LEFT); + result = ec_write(conf->fn_win_swap.address, conf->fn_win_swap.fn_right_value); if (streq(buf, "right")) - result = ec_write(MSI_EC_FN_WIN_ADDRESS, MSI_EC_WIN_KEY_RIGHT); + result = ec_write(conf->fn_win_swap.address, conf->fn_win_swap.fn_left_value); if (result < 0) return result; @@ -281,20 +305,30 @@ static ssize_t battery_mode_show(struct device *device, u8 rdata; int result; - result = ec_read(MSI_EC_BATTERY_MODE_ADDRESS, &rdata); + result = ec_read(conf->battery_mode.address, &rdata); if (result < 0) return result; - switch (rdata) { - case MSI_EC_BATTERY_MODE_MAX_CHARGE: + if (rdata == conf->battery_mode.modes[2]) { return sprintf(buf, "%s\n", "max"); - case MSI_EC_BATTERY_MODE_MEDIUM_CHARGE: + } else if (rdata == conf->battery_mode.modes[1]) { return sprintf(buf, "%s\n", "medium"); - case MSI_EC_BATTERY_MODE_MIN_CHARGE: + } else if (rdata == conf->battery_mode.modes[0]) { return sprintf(buf, "%s\n", "min"); - default: + } else { return sprintf(buf, "%s (%i)\n", "unknown", rdata); } + +// switch (rdata) { +// case conf->battery_mode.modes[2]: +// return sprintf(buf, "%s\n", "max"); +// case conf->battery_mode.modes[1]: +// return sprintf(buf, "%s\n", "medium"); +// case conf->battery_mode.modes[0]: +// return sprintf(buf, "%s\n", "min"); +// default: +// return sprintf(buf, "%s (%i)\n", "unknown", rdata); +// } } static ssize_t battery_mode_store(struct device *dev, @@ -304,16 +338,16 @@ static ssize_t battery_mode_store(struct device *dev, int result = -EINVAL; if (streq(buf, "max")) - result = ec_write(MSI_EC_BATTERY_MODE_ADDRESS, - MSI_EC_BATTERY_MODE_MAX_CHARGE); + result = ec_write(conf->battery_mode.address, + conf->battery_mode.modes[2]); - if (streq(buf, "medium")) - result = ec_write(MSI_EC_BATTERY_MODE_ADDRESS, - MSI_EC_BATTERY_MODE_MEDIUM_CHARGE); + else if (streq(buf, "medium")) + result = ec_write(conf->battery_mode.address, + conf->battery_mode.modes[1]); - if (streq(buf, "min")) - result = ec_write(MSI_EC_BATTERY_MODE_ADDRESS, - MSI_EC_BATTERY_MODE_MIN_CHARGE); + else if (streq(buf, "min")) + result = ec_write(conf->battery_mode.address, + conf->battery_mode.modes[0]); if (result < 0) return result; @@ -327,18 +361,26 @@ static ssize_t cooler_boost_show(struct device *device, u8 rdata; int result; - result = ec_read(MSI_EC_COOLER_BOOST_ADDRESS, &rdata); + result = ec_read(conf->cooler_boost.address, &rdata); if (result < 0) return result; - switch (rdata) { - case MSI_EC_COOLER_BOOST_ON: + if (rdata == conf->cooler_boost.on_value) { return sprintf(buf, "%s\n", "on"); - case MSI_EC_COOLER_BOOST_OFF: + } else if (rdata == conf->cooler_boost.off_value) { return sprintf(buf, "%s\n", "off"); - default: - return sprintf(buf, "%s (%i)\n", "unknown", rdata); } + + return sprintf(buf, "%s (%i)\n", "unknown", rdata); + +// switch (rdata) { +// case conf->cooler_boost.on_value: +// return sprintf(buf, "%s\n", "on"); +// case conf->cooler_boost.off_value: +// return sprintf(buf, "%s\n", "off"); +// default: +// return sprintf(buf, "%s (%i)\n", "unknown", rdata); +// } } static ssize_t cooler_boost_store(struct device *dev, @@ -348,12 +390,12 @@ static ssize_t cooler_boost_store(struct device *dev, int result = -EINVAL; if (streq(buf, "on")) - result = ec_write(MSI_EC_COOLER_BOOST_ADDRESS, - MSI_EC_COOLER_BOOST_ON); + result = ec_write(conf->cooler_boost.address, + conf->cooler_boost.on_value); - if (streq(buf, "off")) - result = ec_write(MSI_EC_COOLER_BOOST_ADDRESS, - MSI_EC_COOLER_BOOST_OFF); + else if (streq(buf, "off")) + result = ec_write(conf->cooler_boost.address, + conf->cooler_boost.off_value); if (result < 0) return result; @@ -367,51 +409,77 @@ static ssize_t shift_mode_show(struct device *device, u8 rdata; int result; - result = ec_read(MSI_EC_SHIFT_MODE_ADDRESS, &rdata); + result = ec_read(conf->shift_mode.address, &rdata); if (result < 0) return result; - switch (rdata) { - case MSI_EC_SHIFT_MODE_TURBO: - return sprintf(buf, "%s\n", "turbo"); - case MSI_EC_SHIFT_MODE_SPORT: - return sprintf(buf, "%s\n", "sport"); - case MSI_EC_SHIFT_MODE_COMFORT: - return sprintf(buf, "%s\n", "comfort"); - case MSI_EC_SHIFT_MODE_ECO: - return sprintf(buf, "%s\n", "eco"); - case MSI_EC_SHIFT_MODE_OFF: - return sprintf(buf, "%s\n", "off"); - default: + if (rdata == conf->shift_mode.off_value) + return sprintf(buf, "-1\n"); + + unsigned int mode = rdata - conf->shift_mode.base_value; + if (mode > conf->shift_mode.max_mode) return sprintf(buf, "%s (%i)\n", "unknown", rdata); - } + + return sprintf(buf, "%i", mode); + +// switch (rdata) { +// case MSI_EC_SHIFT_MODE_TURBO: +// return sprintf(buf, "%s\n", "turbo"); +// case MSI_EC_SHIFT_MODE_SPORT: +// return sprintf(buf, "%s\n", "sport"); +// case MSI_EC_SHIFT_MODE_COMFORT: +// return sprintf(buf, "%s\n", "comfort"); +// case MSI_EC_SHIFT_MODE_ECO: +// return sprintf(buf, "%s\n", "eco"); +// case MSI_EC_SHIFT_MODE_OFF: +// return sprintf(buf, "%s\n", "off"); +// default: +// return sprintf(buf, "%s (%i)\n", "unknown", rdata); +// } } static ssize_t shift_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int result = -EINVAL; - - if (streq(buf, "turbo")) - result = ec_write(MSI_EC_SHIFT_MODE_ADDRESS, - MSI_EC_SHIFT_MODE_TURBO); + int wdata; + int result; +// int result = -EINVAL; - if (streq(buf, "sport")) - result = ec_write(MSI_EC_SHIFT_MODE_ADDRESS, - MSI_EC_SHIFT_MODE_SPORT); + result = kstrtoint(buf, 10, &wdata); + if (result < 0) + return result; - if (streq(buf, "comfort")) - result = ec_write(MSI_EC_SHIFT_MODE_ADDRESS, - MSI_EC_SHIFT_MODE_COMFORT); + if (wdata == -1) { // off + result = ec_write(conf->shift_mode.address, + conf->shift_mode.off_value); + } else { // on (or invalid) + if ((unsigned int)wdata > conf->shift_mode.max_mode) + return -EINVAL; - if (streq(buf, "eco")) - result = ec_write(MSI_EC_SHIFT_MODE_ADDRESS, - MSI_EC_SHIFT_MODE_ECO); + result = ec_write(conf->shift_mode.address, + wdata + conf->shift_mode.base_value); + } - if (streq(buf, "off")) - result = ec_write(MSI_EC_SHIFT_MODE_ADDRESS, - MSI_EC_SHIFT_MODE_OFF); +// if (streq(buf, "turbo")) +// result = ec_write(conf->shift_mode.address, +// MSI_EC_SHIFT_MODE_TURBO); +// +// else if (streq(buf, "sport")) +// result = ec_write(conf->shift_mode.address, +// MSI_EC_SHIFT_MODE_SPORT); +// +// else if (streq(buf, "comfort")) +// result = ec_write(conf->shift_mode.address, +// MSI_EC_SHIFT_MODE_COMFORT); +// +// else if (streq(buf, "eco")) +// result = ec_write(conf->shift_mode.address, +// MSI_EC_SHIFT_MODE_ECO); +// +// else if (streq(buf, "off")) +// result = ec_write(conf->shift_mode.address, +// MSI_EC_SHIFT_MODE_OFF); if (result < 0) return result; @@ -425,38 +493,59 @@ static ssize_t fan_mode_show(struct device *device, u8 rdata; int result; - result = ec_read(MSI_EC_FAN_MODE_ADDRESS, &rdata); + result = ec_read(conf->fan_mode.address, &rdata); if (result < 0) return result; - switch (rdata) { - case MSI_EC_FAN_MODE_AUTO: - return sprintf(buf, "%s\n", "auto"); - case MSI_EC_FAN_MODE_BASIC: - return sprintf(buf, "%s\n", "basic"); - case MSI_EC_FAN_MODE_ADVANCED: - return sprintf(buf, "%s\n", "advanced"); - default: - return sprintf(buf, "%s (%i)\n", "unknown", rdata); + for (int i = 0; i <= conf->fan_mode.max_mode; i++) { + if (rdata == conf->fan_mode.mode_values[i]) { + return sprintf(buf, "%i\n", i); + } } + + return sprintf(buf, "%s (%i)\n", "unknown", rdata); + +// switch (rdata) { +// case MSI_EC_FAN_MODE_AUTO: +// return sprintf(buf, "%s\n", "auto"); +// case MSI_EC_FAN_MODE_BASIC: +// return sprintf(buf, "%s\n", "basic"); +// case MSI_EC_FAN_MODE_ADVANCED: +// return sprintf(buf, "%s\n", "advanced"); +// default: +// return sprintf(buf, "%s (%i)\n", "unknown", rdata); +// } } static ssize_t fan_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int result = -EINVAL; + u8 wdata; + int result; +// int result = -EINVAL; - if (streq(buf, "auto")) - result = - ec_write(MSI_EC_FAN_MODE_ADDRESS, MSI_EC_FAN_MODE_AUTO); + result = kstrtou8(buf, 10, &wdata); + if (result < 0) + return result; - if (streq(buf, "basic")) - result = ec_write(MSI_EC_FAN_MODE_ADDRESS, - MSI_EC_FAN_MODE_BASIC); + if (wdata > conf->fan_mode.max_mode) { + result = -EINVAL; + } else { + result = ec_write(conf->fan_mode.address, + conf->fan_mode.mode_values[wdata]); + } - if (streq(buf, "advanced")) - result = ec_write(MSI_EC_FAN_MODE_ADDRESS, - MSI_EC_FAN_MODE_ADVANCED); +// if (streq(buf, "auto")) +// result = +// ec_write(MSI_EC_FAN_MODE_ADDRESS, MSI_EC_FAN_MODE_AUTO); +// +// if (streq(buf, "basic")) +// result = ec_write(MSI_EC_FAN_MODE_ADDRESS, +// MSI_EC_FAN_MODE_BASIC); +// +// if (streq(buf, "advanced")) +// result = ec_write(MSI_EC_FAN_MODE_ADDRESS, +// MSI_EC_FAN_MODE_ADVANCED); if (result < 0) return result; @@ -471,7 +560,7 @@ static ssize_t fw_version_show(struct device *device, int result; memset(rdata, 0, MSI_EC_FW_VERSION_LENGTH + 1); - result = ec_read_seq(MSI_EC_FW_VERSION_ADDRESS, rdata, + result = ec_read_seq(conf->fw.version_address, rdata, MSI_EC_FW_VERSION_LENGTH); if (result < 0) return result; @@ -488,14 +577,14 @@ static ssize_t fw_release_date_show(struct device *device, int year, month, day, hour, minute, second; memset(rdate, 0, MSI_EC_FW_DATE_LENGTH + 1); - result = ec_read_seq(MSI_EC_FW_DATE_ADDRESS, rdate, + result = ec_read_seq(conf->fw.date_address, rdate, MSI_EC_FW_DATE_LENGTH); if (result < 0) return result; sscanf(rdate, "%02d%02d%04d", &month, &day, &year); memset(rtime, 0, MSI_EC_FW_TIME_LENGTH + 1); - result = ec_read_seq(MSI_EC_FW_TIME_ADDRESS, rtime, + result = ec_read_seq(conf->fw.time_address, rtime, MSI_EC_FW_TIME_LENGTH); if (result < 0) return result; From 3de62eb5298be668aebc65cf60b2572a668dad5e Mon Sep 17 00:00:00 2001 From: teackot Date: Thu, 5 Jan 2023 01:14:24 +0300 Subject: [PATCH 02/28] Flip and check bits instead of writing and checking whole bytes for fn/super swap --- constants.h | 5 ++-- msi-ec.c | 66 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/constants.h b/constants.h index 74c5bbe..ed93581 100644 --- a/constants.h +++ b/constants.h @@ -76,8 +76,7 @@ static int MSI_EC_KBD_BL_STATE[4] = { struct msi_ec_fn_win_swap_conf { int address; - int fn_left_value; - int fn_right_value; + int bit; }; struct msi_ec_battery_mode_conf { @@ -191,7 +190,7 @@ struct msi_ec_conf { static struct msi_ec_conf CONFIGURATIONS[1] = { { - .fn_win_swap = { 0xbf, 0x40, 0x50 }, + .fn_win_swap = { 0xbf, 4 }, .battery_mode = { 0xef, { 0xbc, 0xd0, 0xe4 } }, .power_status = { 0x30, 1, 0 }, .charge = { 0x42, 0x31 }, diff --git a/msi-ec.c b/msi-ec.c index 5fbd03f..ca701c9 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -219,14 +219,20 @@ static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, if (result < 0) return result; - if (rdata == conf->fn_win_swap.fn_left_value) { - return sprintf(buf, "%s\n", "left"); - } else if (rdata == conf->fn_win_swap.fn_right_value) { + if (rdata & (1 << conf->fn_win_swap.bit)) { return sprintf(buf, "%s\n", "right"); } else { - return sprintf(buf, "%s (%i)\n", "unknown", rdata); + return sprintf(buf, "%s\n", "left"); } +// if (rdata == conf->fn_win_swap.fn_left_value) { +// return sprintf(buf, "%s\n", "left"); +// } else if (rdata == conf->fn_win_swap.fn_right_value) { +// return sprintf(buf, "%s\n", "right"); +// } else { +// return sprintf(buf, "%s (%i)\n", "unknown", rdata); +// } + // switch (rdata) { // case conf->fn_win_swap.fn_left_value: // return sprintf(buf, "%s\n", "left"); @@ -240,13 +246,22 @@ static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, static ssize_t fn_key_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int result = -EINVAL; + u8 rdata; + int result; + + result = ec_read(conf->fn_win_swap.address, &rdata); + if (result < 0) + return result; - if (streq(buf, "left")) - result = ec_write(conf->fn_win_swap.address, conf->fn_win_swap.fn_left_value); + result = -EINVAL; - if (streq(buf, "right")) - result = ec_write(conf->fn_win_swap.address, conf->fn_win_swap.fn_right_value); + if (streq(buf, "right")) { + rdata |= 1 << conf->fn_win_swap.bit; + result = ec_write(conf->fn_win_swap.address, rdata); + } else if (streq(buf, "left")) { + rdata &= ~(1 << conf->fn_win_swap.bit); + result = ec_write(conf->fn_win_swap.address, rdata); + } if (result < 0) return result; @@ -264,14 +279,20 @@ static ssize_t win_key_show(struct device *device, if (result < 0) return result; - if (rdata == conf->fn_win_swap.fn_right_value) { + if (rdata & (1 << conf->fn_win_swap.bit)) { return sprintf(buf, "%s\n", "left"); - } else if (rdata == conf->fn_win_swap.fn_left_value) { - return sprintf(buf, "%s\n", "right"); } else { - return sprintf(buf, "%s (%i)\n", "unknown", rdata); + return sprintf(buf, "%s\n", "right"); } +// if (rdata == conf->fn_win_swap.fn_right_value) { +// return sprintf(buf, "%s\n", "left"); +// } else if (rdata == conf->fn_win_swap.fn_left_value) { +// return sprintf(buf, "%s\n", "right"); +// } else { +// return sprintf(buf, "%s (%i)\n", "unknown", rdata); +// } + // switch (rdata) { // case conf->fn_win_swap.fn_right_value: // return sprintf(buf, "%s\n", "left"); @@ -285,13 +306,22 @@ static ssize_t win_key_show(struct device *device, static ssize_t win_key_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int result = -EINVAL; + u8 rdata; + int result; + + result = ec_read(conf->fn_win_swap.address, &rdata); + if (result < 0) + return result; - if (streq(buf, "left")) - result = ec_write(conf->fn_win_swap.address, conf->fn_win_swap.fn_right_value); + result = -EINVAL; - if (streq(buf, "right")) - result = ec_write(conf->fn_win_swap.address, conf->fn_win_swap.fn_left_value); + if (streq(buf, "left")) { + rdata |= 1 << conf->fn_win_swap.bit; + result = ec_write(conf->fn_win_swap.address, rdata); + } else if (streq(buf, "right")) { + rdata &= ~(1 << conf->fn_win_swap.bit); + result = ec_write(conf->fn_win_swap.address, rdata); + } if (result < 0) return result; From 0fdcaf7f1e6488688a45d19f5cdb6ed590358d2d Mon Sep 17 00:00:00 2001 From: teackot Date: Thu, 5 Jan 2023 05:10:05 +0300 Subject: [PATCH 03/28] Store all configuration in structures rather than constants. Change single bits instead of bytes where needed. --- Makefile | 2 + msi-ec.c | 212 ++++++++++++++--------- constants.h => registers_configuration.h | 150 ++++++---------- 3 files changed, 186 insertions(+), 178 deletions(-) rename constants.h => registers_configuration.h (51%) diff --git a/Makefile b/Makefile index e5cf1c5..36d42eb 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,8 @@ load: unload: -rmmod msi-ec +reload: unload load + install: mkdir -p /lib/modules/$(shell uname -r)/extra cp msi-ec.ko /lib/modules/$(shell uname -r)/extra diff --git a/msi-ec.c b/msi-ec.c index ca701c9..1130cc7 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -31,7 +31,7 @@ * */ -#include "constants.h" +#include "registers_configuration.h" #include #include @@ -44,6 +44,10 @@ #define streq(x, y) (strcmp(x, y) == 0 || strcmp(x, y "\n") == 0) +#define set_bit(v, b) (v |= (1 << b)) +#define unset_bit(v, b) (v &= ~(1 << b)) +#define check_bit(v, b) ((bool)((v >> b) & 1)) + static int ec_read_seq(u8 addr, u8 *buf, int len) { int result; @@ -56,6 +60,48 @@ static int ec_read_seq(u8 addr, u8 *buf, int len) return 0; } +static int ec_set_bit(u8 addr, u8 bit) +{ + int result; + u8 stored; + + result = ec_read(addr, &stored); + if (result < 0) + return result; + + set_bit(stored, bit); + + return ec_write(addr, stored); +} + +static int ec_unset_bit(u8 addr, u8 bit) +{ + int result; + u8 stored; + + result = ec_read(addr, &stored); + if (result < 0) + return result; + + unset_bit(stored, bit); + + return ec_write(addr, stored); +} + +static int ec_check_bit(u8 addr, u8 bit, bool *output) +{ + int result; + u8 stored; + + result = ec_read(addr, &stored); + if (result < 0) + return result; + + *output = check_bit(stored, bit); + + return 0; +} + // ============================================================ // // Sysfs power_supply subsystem // ============================================================ // @@ -167,19 +213,15 @@ static struct acpi_battery_hook battery_hook = { static ssize_t webcam_show(struct device *device, struct device_attribute *attr, char *buf) { - u8 rdata; int result; + bool bit_value; - result = ec_read(conf->webcam.address, &rdata); - if (result < 0) - return result; + result = ec_check_bit(conf->webcam.address, conf->webcam.bit, &bit_value); - if (rdata == conf->webcam.on_value) { + if (bit_value) { return sprintf(buf, "%s\n", "on"); - } else if (rdata == conf->webcam.off_value) { - return sprintf(buf, "%s\n", "off"); } else { - return sprintf(buf, "%s (%i)\n", "unknown", rdata); + return sprintf(buf, "%s\n", "off"); } // switch (rdata) { @@ -198,10 +240,10 @@ static ssize_t webcam_store(struct device *dev, struct device_attribute *attr, int result = -EINVAL; if (streq(buf, "on")) - result = ec_write(conf->webcam.address, conf->webcam.on_value); + result = ec_set_bit(conf->webcam.address, conf->webcam.bit); if (streq(buf, "off")) - result = ec_write(conf->webcam.address, conf->webcam.off_value); + result = ec_unset_bit(conf->webcam.address, conf->webcam.bit); if (result < 0) return result; @@ -212,14 +254,12 @@ static ssize_t webcam_store(struct device *dev, struct device_attribute *attr, static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, char *buf) { - u8 rdata; int result; + bool bit_value; - result = ec_read(conf->fn_win_swap.address, &rdata); - if (result < 0) - return result; + result = ec_check_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit, &bit_value); - if (rdata & (1 << conf->fn_win_swap.bit)) { + if (bit_value) { return sprintf(buf, "%s\n", "right"); } else { return sprintf(buf, "%s\n", "left"); @@ -246,21 +286,12 @@ static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, static ssize_t fn_key_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - u8 rdata; int result; - result = ec_read(conf->fn_win_swap.address, &rdata); - if (result < 0) - return result; - - result = -EINVAL; - if (streq(buf, "right")) { - rdata |= 1 << conf->fn_win_swap.bit; - result = ec_write(conf->fn_win_swap.address, rdata); + result = ec_set_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit); } else if (streq(buf, "left")) { - rdata &= ~(1 << conf->fn_win_swap.bit); - result = ec_write(conf->fn_win_swap.address, rdata); + result = ec_unset_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit); } if (result < 0) @@ -272,14 +303,12 @@ static ssize_t fn_key_store(struct device *dev, struct device_attribute *attr, static ssize_t win_key_show(struct device *device, struct device_attribute *attr, char *buf) { - u8 rdata; int result; + bool bit_value; - result = ec_read(conf->fn_win_swap.address, &rdata); - if (result < 0) - return result; + result = ec_check_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit, &bit_value); - if (rdata & (1 << conf->fn_win_swap.bit)) { + if (bit_value) { return sprintf(buf, "%s\n", "left"); } else { return sprintf(buf, "%s\n", "right"); @@ -306,21 +335,12 @@ static ssize_t win_key_show(struct device *device, static ssize_t win_key_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - u8 rdata; int result; - result = ec_read(conf->fn_win_swap.address, &rdata); - if (result < 0) - return result; - - result = -EINVAL; - - if (streq(buf, "left")) { - rdata |= 1 << conf->fn_win_swap.bit; - result = ec_write(conf->fn_win_swap.address, rdata); - } else if (streq(buf, "right")) { - rdata &= ~(1 << conf->fn_win_swap.bit); - result = ec_write(conf->fn_win_swap.address, rdata); + if (streq(buf, "right")) { + result = ec_unset_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit); + } else if (streq(buf, "left")) { + result = ec_set_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit); } if (result < 0) @@ -388,20 +408,31 @@ static ssize_t battery_mode_store(struct device *dev, static ssize_t cooler_boost_show(struct device *device, struct device_attribute *attr, char *buf) { - u8 rdata; int result; + bool bit_value; - result = ec_read(conf->cooler_boost.address, &rdata); - if (result < 0) - return result; + result = ec_check_bit(conf->cooler_boost.address, conf->cooler_boost.bit, &bit_value); - if (rdata == conf->cooler_boost.on_value) { + if (bit_value) { return sprintf(buf, "%s\n", "on"); - } else if (rdata == conf->cooler_boost.off_value) { + } else { return sprintf(buf, "%s\n", "off"); } - return sprintf(buf, "%s (%i)\n", "unknown", rdata); +// u8 rdata; +// int result; +// +// result = ec_read(conf->cooler_boost.address, &rdata); +// if (result < 0) +// return result; +// +// if (check_bit(rdata, conf->cooler_boost.bit)) { +// return sprintf(buf, "%s\n", "on"); +// } else if (rdata == conf->cooler_boost.off_value) { +// return sprintf(buf, "%s\n", "off"); +// } +// +// return sprintf(buf, "%s (%i)\n", "unknown", rdata); // switch (rdata) { // case conf->cooler_boost.on_value: @@ -420,12 +451,12 @@ static ssize_t cooler_boost_store(struct device *dev, int result = -EINVAL; if (streq(buf, "on")) - result = ec_write(conf->cooler_boost.address, - conf->cooler_boost.on_value); + result = ec_set_bit(conf->cooler_boost.address, + conf->cooler_boost.bit); else if (streq(buf, "off")) - result = ec_write(conf->cooler_boost.address, - conf->cooler_boost.off_value); + result = ec_unset_bit(conf->cooler_boost.address, + conf->cooler_boost.bit); if (result < 0) return result; @@ -450,7 +481,7 @@ static ssize_t shift_mode_show(struct device *device, if (mode > conf->shift_mode.max_mode) return sprintf(buf, "%s (%i)\n", "unknown", rdata); - return sprintf(buf, "%i", mode); + return sprintf(buf, "%i\n", mode); // switch (rdata) { // case MSI_EC_SHIFT_MODE_TURBO: @@ -657,7 +688,7 @@ static ssize_t cpu_realtime_temperature_show(struct device *device, u8 rdata; int result; - result = ec_read(MSI_EC_CPU_REALTIME_TEMPERATURE_ADDRESS, &rdata); + result = ec_read(conf->cpu.rt_temp_address, &rdata); if (result < 0) return result; @@ -671,18 +702,18 @@ static ssize_t cpu_realtime_fan_speed_show(struct device *device, u8 rdata; int result; - result = ec_read(MSI_EC_CPU_REALTIME_FAN_SPEED_ADDRESS, &rdata); + result = ec_read(conf->cpu.rt_fan_speed_address, &rdata); if (result < 0) return result; - if (rdata < MSI_EC_CPU_REALTIME_FAN_SPEED_BASE_MIN || - rdata > MSI_EC_CPU_REALTIME_FAN_SPEED_BASE_MAX) + if ((rdata < conf->cpu.rt_fan_speed_base_min || + rdata > conf->cpu.rt_fan_speed_base_max)) return -EINVAL; return sprintf(buf, "%i\n", - 100 * (rdata - MSI_EC_CPU_REALTIME_FAN_SPEED_BASE_MIN) / - (MSI_EC_CPU_REALTIME_FAN_SPEED_BASE_MAX - - MSI_EC_CPU_REALTIME_FAN_SPEED_BASE_MIN)); + 100 * (rdata - conf->cpu.rt_fan_speed_base_min) / + (conf->cpu.rt_fan_speed_base_max - + conf->cpu.rt_fan_speed_base_min)); } static ssize_t cpu_basic_fan_speed_show(struct device *device, @@ -692,18 +723,18 @@ static ssize_t cpu_basic_fan_speed_show(struct device *device, u8 rdata; int result; - result = ec_read(MSI_EC_CPU_BASIC_FAN_SPEED_ADDRESS, &rdata); + result = ec_read(conf->cpu.bs_fan_speed_address, &rdata); if (result < 0) return result; - if (rdata < MSI_EC_CPU_BASIC_FAN_SPEED_BASE_MIN || - rdata > MSI_EC_CPU_BASIC_FAN_SPEED_BASE_MAX) + if (rdata < conf->cpu.bs_fan_speed_base_min || + rdata > conf->cpu.bs_fan_speed_base_max) return -EINVAL; return sprintf(buf, "%i\n", - 100 * (rdata - MSI_EC_CPU_BASIC_FAN_SPEED_BASE_MIN) / - (MSI_EC_CPU_BASIC_FAN_SPEED_BASE_MAX - - MSI_EC_CPU_BASIC_FAN_SPEED_BASE_MIN)); + 100 * (rdata - conf->cpu.bs_fan_speed_base_min) / + (conf->cpu.bs_fan_speed_base_max - + conf->cpu.bs_fan_speed_base_min)); } static ssize_t cpu_basic_fan_speed_store(struct device *dev, @@ -720,10 +751,10 @@ static ssize_t cpu_basic_fan_speed_store(struct device *dev, if (wdata > 100) return -EINVAL; - result = ec_write(MSI_EC_CPU_BASIC_FAN_SPEED_ADDRESS, - (wdata * (MSI_EC_CPU_BASIC_FAN_SPEED_BASE_MAX - - MSI_EC_CPU_BASIC_FAN_SPEED_BASE_MIN) + - 100 * MSI_EC_CPU_BASIC_FAN_SPEED_BASE_MIN) / + result = ec_write(conf->cpu.bs_fan_speed_address, + (wdata * (conf->cpu.bs_fan_speed_base_max - + conf->cpu.bs_fan_speed_base_min) + + 100 * conf->cpu.bs_fan_speed_base_min) / 100); if (result < 0) return result; @@ -779,7 +810,7 @@ static ssize_t gpu_realtime_temperature_show(struct device *device, u8 rdata; int result; - result = ec_read(MSI_EC_GPU_REALTIME_TEMPERATURE_ADDRESS, &rdata); + result = ec_read(conf->gpu.rt_temp_address, &rdata); if (result < 0) return result; @@ -793,7 +824,7 @@ static ssize_t gpu_realtime_fan_speed_show(struct device *device, u8 rdata; int result; - result = ec_read(MSI_EC_GPU_REALTIME_FAN_SPEED_ADDRESS, &rdata); + result = ec_read(conf->gpu.rt_fan_speed_address, &rdata); if (result < 0) return result; @@ -866,27 +897,41 @@ static struct platform_driver msi_platform_driver = { static int micmute_led_sysfs_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - u8 state = brightness ? MSI_EC_LED_STATE_ON : MSI_EC_LED_STATE_OFF; - int result = ec_write(MSI_EC_LED_MICMUTE_ADDRESS, state); + int result; + + if (brightness) { + result = ec_set_bit(conf->leds.micmute_led_address, conf->leds.bit); + } else { + result = ec_unset_bit(conf->leds.micmute_led_address, conf->leds.bit); + } + if (result < 0) return result; + return 0; } static int mute_led_sysfs_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - u8 state = brightness ? MSI_EC_LED_STATE_ON : MSI_EC_LED_STATE_OFF; - int result = ec_write(MSI_EC_LED_MUTE_ADDRESS, state); + int result; + + if (brightness) { + result = ec_set_bit(conf->leds.mute_led_address, conf->leds.bit); + } else { + result = ec_unset_bit(conf->leds.mute_led_address, conf->leds.bit); + } + if (result < 0) return result; + return 0; } static enum led_brightness kbd_bl_sysfs_get(struct led_classdev *led_cdev) { u8 rdata; - int result = ec_read(MSI_EC_KBD_BL_ADDRESS, &rdata); + int result = ec_read(conf->kbd_bl.bl_state_address, &rdata); if (result < 0) return 0; return rdata & MSI_EC_KBD_BL_STATE_MASK; @@ -898,8 +943,8 @@ static int kbd_bl_sysfs_set(struct led_classdev *led_cdev, u8 wdata; if (brightness < 0 || brightness > 3) return -1; - wdata = MSI_EC_KBD_BL_STATE[brightness]; - return ec_write(MSI_EC_KBD_BL_ADDRESS, wdata); + wdata = conf->kbd_bl.state_base_value | brightness; + return ec_write(conf->kbd_bl.bl_state_address, wdata); } static struct led_classdev micmute_led_cdev = { @@ -982,6 +1027,7 @@ static void __exit msi_ec_exit(void) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jose Angel Pastrana "); MODULE_AUTHOR("Aakash Singh "); +MODULE_AUTHOR("Nikita Kravets "); MODULE_DESCRIPTION("MSI Embedded Controller"); MODULE_VERSION("0.08"); diff --git a/constants.h b/registers_configuration.h similarity index 51% rename from constants.h rename to registers_configuration.h index ed93581..55f8a3c 100644 --- a/constants.h +++ b/registers_configuration.h @@ -4,75 +4,12 @@ #include #define MSI_DRIVER_NAME "msi-ec" -#define MSI_EC_WEBCAM_ADDRESS 0x2e -#define MSI_EC_WEBCAM_ON 0x4a -#define MSI_EC_WEBCAM_OFF 0x48 -#define MSI_EC_FN_WIN_ADDRESS 0xbf -#define MSI_EC_FN_KEY_LEFT 0x40 -#define MSI_EC_FN_KEY_RIGHT 0x50 -#define MSI_EC_WIN_KEY_LEFT 0x50 -#define MSI_EC_WIN_KEY_RIGHT 0x40 -#define MSI_EC_BATTERY_MODE_ADDRESS 0xef -#define MSI_EC_BATTERY_MODE_MAX_CHARGE 0xe4 -#define MSI_EC_BATTERY_MODE_MEDIUM_CHARGE 0xd0 -#define MSI_EC_BATTERY_MODE_MIN_CHARGE 0xbc -#define MSI_EC_COOLER_BOOST_ADDRESS 0x98 -#define MSI_EC_COOLER_BOOST_ON 0x82 -#define MSI_EC_COOLER_BOOST_OFF 0x02 -#define MSI_EC_SHIFT_MODE_ADDRESS 0xf2 -#define MSI_EC_SHIFT_MODE_TURBO 0xc4 -#define MSI_EC_SHIFT_MODE_SPORT 0xc0 -#define MSI_EC_SHIFT_MODE_COMFORT 0xc1 -#define MSI_EC_SHIFT_MODE_ECO 0xc2 -#define MSI_EC_SHIFT_MODE_OFF 0x80 -#define MSI_EC_FW_VERSION_ADDRESS 0xa0 -#define MSI_EC_FW_VERSION_LENGTH 12 -#define MSI_EC_FW_DATE_ADDRESS 0xac -#define MSI_EC_FW_DATE_LENGTH 8 -#define MSI_EC_FW_TIME_ADDRESS 0xb4 -#define MSI_EC_FW_TIME_LENGTH 8 -#define MSI_EC_CHARGE_CONTROL_ADDRESS 0xef -#define MSI_EC_CHARGE_CONTROL_OFFSET_START 0x8a -#define MSI_EC_CHARGE_CONTROL_OFFSET_END 0x80 -#define MSI_EC_CHARGE_CONTROL_RANGE_MIN 0x8a -#define MSI_EC_CHARGE_CONTROL_RANGE_MAX 0xe4 -#define MSI_EC_CPU_REALTIME_TEMPERATURE_ADDRESS 0x68 -#define MSI_EC_CPU_REALTIME_FAN_SPEED_ADDRESS 0x71 -#define MSI_EC_CPU_REALTIME_FAN_SPEED_BASE_MIN 0x19 -#define MSI_EC_CPU_REALTIME_FAN_SPEED_BASE_MAX 0x37 -#define MSI_EC_CPU_BASIC_FAN_SPEED_ADDRESS 0x89 -#define MSI_EC_CPU_BASIC_FAN_SPEED_BASE_MIN 0x00 -#define MSI_EC_CPU_BASIC_FAN_SPEED_BASE_MAX 0x0f -#define MSI_EC_GPU_REALTIME_TEMPERATURE_ADDRESS 0x80 -#define MSI_EC_GPU_REALTIME_FAN_SPEED_ADDRESS 0x89 -#define MSI_EC_FAN_MODE_ADDRESS 0xf4 -#define MSI_EC_FAN_MODE_AUTO 0x0d -#define MSI_EC_FAN_MODE_BASIC 0x4d -#define MSI_EC_FAN_MODE_ADVANCED 0x8d - -#define MSI_EC_LED_MICMUTE_ADDRESS 0x2b -#define MSI_EC_LED_MUTE_ADDRESS 0x2c -#define MSI_EC_LED_STATE_MASK 0x4 -#define MSI_EC_LED_STATE_OFF 0x80 -#define MSI_EC_LED_STATE_ON 0x84 - -#define MSI_EC_KBD_BL_ADDRESS 0xf3 -#define MSI_EC_KBD_BL_STATE_MASK 0x3 -#define MSI_EC_KBD_BL_STATE_OFF 0x80 -#define MSI_EC_KBD_BL_STATE_ON 0x81 -#define MSI_EC_KBD_BL_STATE_HALF 0x82 -#define MSI_EC_KBD_BL_STATE_FULL 0x83 -static int MSI_EC_KBD_BL_STATE[4] = { - MSI_EC_KBD_BL_STATE_OFF, - MSI_EC_KBD_BL_STATE_ON, - MSI_EC_KBD_BL_STATE_HALF, - MSI_EC_KBD_BL_STATE_FULL}; - -#define MSI_EC_CAMERA_ADDRESS 0x2e -#define MSI_EC_CAMERA_HARD_ADDRESS 0x2f /* hotkey has no effect if this address disables the cam*/ -#define MSI_EC_CAMERA_STATE_MASK 0x2 -#define MSI_EC_CAMERA_STATE_OFF 0x80 -#define MSI_EC_CAMERA_STATE_ON 0x84 + +struct msi_ec_webcam_conf { + int address; + int hard_address; + int bit; +}; struct msi_ec_fn_win_swap_conf { int address; @@ -97,8 +34,7 @@ struct msi_ec_charge_conf { struct msi_ec_cooler_boost_conf { int address; - u8 on_value; - u8 off_value; + int bit; }; struct msi_ec_shift_mode_conf { @@ -148,12 +84,13 @@ struct msi_ec_fan_mode_conf { }; struct msi_ec_led_conf { - int mic_mute_led_address; + int micmute_led_address; int mute_led_address; int base_value; int bit; }; +#define MSI_EC_KBD_BL_STATE_MASK 0x3 struct msi_ec_kbd_bl_conf { int bl_mode_address; int bl_modes[2]; @@ -164,14 +101,8 @@ struct msi_ec_kbd_bl_conf { int max_state; }; -struct msi_ec_webcam_conf { - int address; - int hard_address; - u8 on_value; - u8 off_value; -}; - struct msi_ec_conf { + struct msi_ec_webcam_conf webcam; struct msi_ec_fn_win_swap_conf fn_win_swap; struct msi_ec_battery_mode_conf battery_mode; struct msi_ec_power_status_conf power_status; @@ -185,19 +116,54 @@ struct msi_ec_conf { struct msi_ec_fan_mode_conf fan_mode; struct msi_ec_led_conf leds; struct msi_ec_kbd_bl_conf kbd_bl; - struct msi_ec_webcam_conf webcam; }; static struct msi_ec_conf CONFIGURATIONS[1] = { { - .fn_win_swap = { 0xbf, 4 }, - .battery_mode = { 0xef, { 0xbc, 0xd0, 0xe4 } }, - .power_status = { 0x30, 1, 0 }, - .charge = { 0x42, 0x31 }, - .cooler_boost = { 0x98, 0x82, 0x02 }, - .shift_mode = { 0xf2, 0x80, 0xc0, 4 }, - .fw = { 0xa0, 0xac, 0xb4 }, - .charge_control = { 0xef, 0x8a, 0x80, 0x8a, 0xe4 }, + .webcam = { + .address = 0x2e, + .hard_address = 0x2f, + .bit = 1, + }, + .fn_win_swap = { + .address = 0xbf, + .bit = 4, + }, + .battery_mode = { + .address = 0xef, + .modes = { 0xbc, 0xd0, 0xe4 }, + }, + .power_status = { + .address = 0x30, + .lid_open_bit = 1, + .ac_connected_bit = 0, + }, + .charge = { + .battery_charge_address = 0x42, + .charging_status_address = 0x31, + }, + .cooler_boost = { + .address = 0x98, + .bit = 7, + }, + .shift_mode = { + .address = 0xf2, + .off_value = 0x80, + .base_value = 0xc0, + .max_mode = 4, + }, + .fw = { + .version_address = 0xa0, + .date_address = 0xac, + .time_address = 0xb4, + }, + .charge_control = { + .address = 0xef, + .offset_start = 0x8a, + .offset_end = 0x80, + .range_min = 0x8a, + .range_max = 0xe4, + }, .cpu = { .rt_temp_address = 0x68, .rt_fan_speed_address = 0x71, @@ -217,7 +183,7 @@ static struct msi_ec_conf CONFIGURATIONS[1] = { .max_mode = 3, }, .leds = { - .mic_mute_led_address = 0x2b, + .micmute_led_address = 0x2b, .mute_led_address = 0x2c, .base_value = 0x80, .bit = 2, @@ -230,12 +196,6 @@ static struct msi_ec_conf CONFIGURATIONS[1] = { .state_base_value = 0x80, .max_state = 3, }, - .webcam = { - .address = 0x2e, - .hard_address = 0x2f, - .on_value = 0x84, - .off_value = 0x80, - }, }, }; From b9fa42699ab25d5e9cea212e8e66b1ce9bc1ee29 Mon Sep 17 00:00:00 2001 From: teackot Date: Thu, 5 Jan 2023 21:23:51 +0300 Subject: [PATCH 04/28] Implemented three firmware configurations; configuration is determined during module initialization; added battery_info entries; added power_status entries; removed old commented out code. --- msi-ec.c | 425 +++++++++++++++++++++++++------------- registers_configuration.h | 137 +++--------- 2 files changed, 317 insertions(+), 245 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index 1130cc7..5b02727 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -42,6 +42,183 @@ #include #include +static const char *ALLOWED_FW_0[] = { + "14C1EMS1.101", + "17F2EMS1.106", + NULL, +}; + +static struct msi_ec_conf CONF0 = { + .allowed_fw = ALLOWED_FW_0, + .battery_info = { + .charge_percentage_address = 0x42, + .charging_status_address = 0x31, + }, + .charge_control = { + .address = 0xef, + .offset_start = 0x8a, + .offset_end = 0x80, + .range_min = 0x8a, + .range_max = 0xe4, + }, + .webcam = { + .address = 0x2e, + .hard_address = 0x2f, + .bit = 1, + }, + .fn_win_swap = { + .address = 0xbf, + .bit = 4, + }, + .battery_mode = { + .address = 0xef, + .modes = { 0xbc, 0xd0, 0xe4 }, + }, + .power_status = { + .address = 0x30, + .lid_open_bit = 1, + .ac_connected_bit = 0, + }, + .cooler_boost = { + .address = 0x98, + .bit = 7, + }, + .shift_mode = { + .address = 0xf2, + .off_value = 0x80, + .base_value = 0xc0, + .max_mode = 4, + }, + .fan_mode = { + .address = 0xf4, + .mode_values = { 0x0d, 0x4d, 0x8d }, + .max_mode = 2, + }, + .fw = { + .version_address = 0xa0, + .date_address = 0xac, + .time_address = 0xb4, + }, + .cpu = { + .rt_temp_address = 0x68, + .rt_fan_speed_address = 0x71, + .rt_fan_speed_base_min = 0x19, + .rt_fan_speed_base_max = 0x37, + .bs_fan_speed_address = 0x89, + .bs_fan_speed_base_min = 0x00, + .bs_fan_speed_base_max = 0x0f, + }, + .gpu = { + .rt_temp_address = 0x80, + .rt_fan_speed_address = 0x89, + }, + .leds = { + .micmute_led_address = 0x2b, + .mute_led_address = 0x2c, + .bit = 2, + }, + .kbd_bl = { + .bl_mode_address = 0x2c, // ? + .bl_modes = { 0x00, 0x08 }, // ? + .max_mode = 1, // ? + .bl_state_address = 0xf3, + .state_base_value = 0x80, + .max_state = 3, + }, +}; + +static const char *ALLOWED_FW_1[] = { + "1552EMS1.118", + NULL, +}; + +static struct msi_ec_conf CONF1 = { + .allowed_fw = ALLOWED_FW_1, + .battery_info = { + .charge_percentage_address = 0x42, + .charging_status_address = 0x31, + }, + .charge_control = { + .address = 0xd7, + .offset_start = 0x8a, + .offset_end = 0x80, + .range_min = 0x8a, + .range_max = 0xe4, + }, + .webcam = { + .address = 0x2e, + .hard_address = 0x2f, + .bit = 1, + }, + .fn_win_swap = { + .address = 0xe8, + .bit = 4, + }, + .battery_mode = { + .address = 0xd7, + .modes = { 0xbc, 0xd0, 0xe4 }, + }, + .power_status = { + .address = 0x30, + .lid_open_bit = 1, + .ac_connected_bit = 0, + }, + .cooler_boost = { + .address = 0x98, + .bit = 7, + }, + .shift_mode = { + .address = 0xf2, + .off_value = 0x80, + .base_value = 0xc0, + .max_mode = 2, + }, + .fan_mode = { + .address = 0xd4, + .mode_values = { 0x1d, 0x4d, 0x8d }, + .max_mode = 2, + }, + .fw = { + .version_address = 0xa0, + .date_address = 0xac, + .time_address = 0xb4, + }, + .cpu = { + .rt_temp_address = 0x68, + .rt_fan_speed_address = 0x71, + .rt_fan_speed_base_min = 0x19, + .rt_fan_speed_base_max = 0x37, + .bs_fan_speed_address = 0x89, + .bs_fan_speed_base_min = 0x00, + .bs_fan_speed_base_max = 0x0f, + }, + .gpu = { + .rt_temp_address = 0x80, + .rt_fan_speed_address = 0x89, + }, + .leds = { + .micmute_led_address = 0x2c, + .mute_led_address = 0x2d, + .bit = 1, + }, + .kbd_bl = { + .bl_mode_address = 0x2c, // ? + .bl_modes = { 0x00, 0x08 }, // ? + .max_mode = 1, // ? + .bl_state_address = 0xd3, + .state_base_value = 0x80, + .max_state = 3, + }, +}; + +static struct msi_ec_conf *CONFIGURATIONS[] = { + &CONF0, + &CONF1, + NULL, +}; + +static struct msi_ec_conf *conf = &CONF0; // current configuration + #define streq(x, y) (strcmp(x, y) == 0 || strcmp(x, y "\n") == 0) #define set_bit(v, b) (v |= (1 << b)) @@ -102,10 +279,64 @@ static int ec_check_bit(u8 addr, u8 bit, bool *output) return 0; } +static int ec_get_firmware_version_common_address(u8 buf[MSI_EC_FW_VERSION_LENGTH + 1]) +{ + int result; + + memset(buf, 0, MSI_EC_FW_VERSION_LENGTH + 1); + result = ec_read_seq(MSI_EC_FW_VERSION_ADDRESS, buf, + MSI_EC_FW_VERSION_LENGTH); + if (result < 0) + return result; + + return MSI_EC_FW_VERSION_LENGTH + 1; +} + // ============================================================ // // Sysfs power_supply subsystem // ============================================================ // +static ssize_t charge_percentage_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + u8 rdata; + int result; + + result = ec_read(conf->battery_info.charge_percentage_address, &rdata); + if (result < 0) + return result; + + return sprintf(buf, "%i\n", rdata - 1); +} + +static ssize_t charging_status_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + u8 rdata; + int result; + + result = ec_read(conf->battery_info.charging_status_address, &rdata); + if (result < 0) + return result; + + switch (rdata) { + case MSI_EC_CHARGING_STATUS_NOT_CHARGING: + return sprintf(buf, "%s\n", "Not charging"); + case MSI_EC_CHARGING_STATUS_CHARGING: + return sprintf(buf, "%s\n", "Charging"); + case MSI_EC_CHARGING_STATUS_DISCHARGING: + return sprintf(buf, "%s\n", "Discharging"); + case MSI_EC_CHARGING_STATUS_FULL: + return sprintf(buf, "%s\n", "Full"); + case MSI_EC_CHARGING_STATUS_FULL_NO_POWER: + return sprintf(buf, "%s\n", "Full (no power)"); + default: + return sprintf(buf, "%s (%i)\n", "unknown", rdata); + } +} + static ssize_t charge_control_threshold_show(u8 offset, struct device *device, struct device_attribute *attr, char *buf) @@ -176,10 +407,14 @@ static ssize_t charge_control_end_threshold_store(struct device *dev, dev, attr, buf, count); } +static DEVICE_ATTR_RO(charge_percentage); +static DEVICE_ATTR_RO(charging_status); static DEVICE_ATTR_RW(charge_control_start_threshold); static DEVICE_ATTR_RW(charge_control_end_threshold); static struct attribute *msi_battery_attrs[] = { + &dev_attr_charge_percentage.attr, + &dev_attr_charging_status.attr, &dev_attr_charge_control_start_threshold.attr, &dev_attr_charge_control_end_threshold.attr, NULL, @@ -223,15 +458,6 @@ static ssize_t webcam_show(struct device *device, struct device_attribute *attr, } else { return sprintf(buf, "%s\n", "off"); } - -// switch (rdata) { -// case conf->webcam.on_value: -// return sprintf(buf, "%s\n", "on"); -// case conf->webcam.off_value: -// return sprintf(buf, "%s\n", "off"); -// default: -// return sprintf(buf, "%s (%i)\n", "unknown", rdata); -// } } static ssize_t webcam_store(struct device *dev, struct device_attribute *attr, @@ -264,23 +490,6 @@ static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, } else { return sprintf(buf, "%s\n", "left"); } - -// if (rdata == conf->fn_win_swap.fn_left_value) { -// return sprintf(buf, "%s\n", "left"); -// } else if (rdata == conf->fn_win_swap.fn_right_value) { -// return sprintf(buf, "%s\n", "right"); -// } else { -// return sprintf(buf, "%s (%i)\n", "unknown", rdata); -// } - -// switch (rdata) { -// case conf->fn_win_swap.fn_left_value: -// return sprintf(buf, "%s\n", "left"); -// case conf->fn_win_swap.fn_right_value: -// return sprintf(buf, "%s\n", "right"); -// default: -// return sprintf(buf, "%s (%i)\n", "unknown", rdata); -// } } static ssize_t fn_key_store(struct device *dev, struct device_attribute *attr, @@ -313,23 +522,6 @@ static ssize_t win_key_show(struct device *device, } else { return sprintf(buf, "%s\n", "right"); } - -// if (rdata == conf->fn_win_swap.fn_right_value) { -// return sprintf(buf, "%s\n", "left"); -// } else if (rdata == conf->fn_win_swap.fn_left_value) { -// return sprintf(buf, "%s\n", "right"); -// } else { -// return sprintf(buf, "%s (%i)\n", "unknown", rdata); -// } - -// switch (rdata) { -// case conf->fn_win_swap.fn_right_value: -// return sprintf(buf, "%s\n", "left"); -// case conf->fn_win_swap.fn_left_value: -// return sprintf(buf, "%s\n", "right"); -// default: -// return sprintf(buf, "%s (%i)\n", "unknown", rdata); -// } } static ssize_t win_key_store(struct device *dev, struct device_attribute *attr, @@ -368,17 +560,6 @@ static ssize_t battery_mode_show(struct device *device, } else { return sprintf(buf, "%s (%i)\n", "unknown", rdata); } - -// switch (rdata) { -// case conf->battery_mode.modes[2]: -// return sprintf(buf, "%s\n", "max"); -// case conf->battery_mode.modes[1]: -// return sprintf(buf, "%s\n", "medium"); -// case conf->battery_mode.modes[0]: -// return sprintf(buf, "%s\n", "min"); -// default: -// return sprintf(buf, "%s (%i)\n", "unknown", rdata); -// } } static ssize_t battery_mode_store(struct device *dev, @@ -405,6 +586,32 @@ static ssize_t battery_mode_store(struct device *dev, return count; } +static ssize_t lid_status_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + int result; + bool bit_value; + + result = ec_check_bit(conf->power_status.address, conf->power_status.lid_open_bit, &bit_value); + if (result < 0) + return result; + + return sprintf(buf, "%s\n", bit_value ? "open" : "closed"); +} + +static ssize_t ac_connected_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + int result; + bool bit_value; + + result = ec_check_bit(conf->power_status.address, conf->power_status.ac_connected_bit, &bit_value); + if (result < 0) + return result; + + return sprintf(buf, "%s\n", bit_value ? "1" : "0"); +} + static ssize_t cooler_boost_show(struct device *device, struct device_attribute *attr, char *buf) { @@ -418,30 +625,6 @@ static ssize_t cooler_boost_show(struct device *device, } else { return sprintf(buf, "%s\n", "off"); } - -// u8 rdata; -// int result; -// -// result = ec_read(conf->cooler_boost.address, &rdata); -// if (result < 0) -// return result; -// -// if (check_bit(rdata, conf->cooler_boost.bit)) { -// return sprintf(buf, "%s\n", "on"); -// } else if (rdata == conf->cooler_boost.off_value) { -// return sprintf(buf, "%s\n", "off"); -// } -// -// return sprintf(buf, "%s (%i)\n", "unknown", rdata); - -// switch (rdata) { -// case conf->cooler_boost.on_value: -// return sprintf(buf, "%s\n", "on"); -// case conf->cooler_boost.off_value: -// return sprintf(buf, "%s\n", "off"); -// default: -// return sprintf(buf, "%s (%i)\n", "unknown", rdata); -// } } static ssize_t cooler_boost_store(struct device *dev, @@ -482,21 +665,6 @@ static ssize_t shift_mode_show(struct device *device, return sprintf(buf, "%s (%i)\n", "unknown", rdata); return sprintf(buf, "%i\n", mode); - -// switch (rdata) { -// case MSI_EC_SHIFT_MODE_TURBO: -// return sprintf(buf, "%s\n", "turbo"); -// case MSI_EC_SHIFT_MODE_SPORT: -// return sprintf(buf, "%s\n", "sport"); -// case MSI_EC_SHIFT_MODE_COMFORT: -// return sprintf(buf, "%s\n", "comfort"); -// case MSI_EC_SHIFT_MODE_ECO: -// return sprintf(buf, "%s\n", "eco"); -// case MSI_EC_SHIFT_MODE_OFF: -// return sprintf(buf, "%s\n", "off"); -// default: -// return sprintf(buf, "%s (%i)\n", "unknown", rdata); -// } } static ssize_t shift_mode_store(struct device *dev, @@ -505,7 +673,6 @@ static ssize_t shift_mode_store(struct device *dev, { int wdata; int result; -// int result = -EINVAL; result = kstrtoint(buf, 10, &wdata); if (result < 0) @@ -522,26 +689,6 @@ static ssize_t shift_mode_store(struct device *dev, wdata + conf->shift_mode.base_value); } -// if (streq(buf, "turbo")) -// result = ec_write(conf->shift_mode.address, -// MSI_EC_SHIFT_MODE_TURBO); -// -// else if (streq(buf, "sport")) -// result = ec_write(conf->shift_mode.address, -// MSI_EC_SHIFT_MODE_SPORT); -// -// else if (streq(buf, "comfort")) -// result = ec_write(conf->shift_mode.address, -// MSI_EC_SHIFT_MODE_COMFORT); -// -// else if (streq(buf, "eco")) -// result = ec_write(conf->shift_mode.address, -// MSI_EC_SHIFT_MODE_ECO); -// -// else if (streq(buf, "off")) -// result = ec_write(conf->shift_mode.address, -// MSI_EC_SHIFT_MODE_OFF); - if (result < 0) return result; @@ -565,17 +712,6 @@ static ssize_t fan_mode_show(struct device *device, } return sprintf(buf, "%s (%i)\n", "unknown", rdata); - -// switch (rdata) { -// case MSI_EC_FAN_MODE_AUTO: -// return sprintf(buf, "%s\n", "auto"); -// case MSI_EC_FAN_MODE_BASIC: -// return sprintf(buf, "%s\n", "basic"); -// case MSI_EC_FAN_MODE_ADVANCED: -// return sprintf(buf, "%s\n", "advanced"); -// default: -// return sprintf(buf, "%s (%i)\n", "unknown", rdata); -// } } static ssize_t fan_mode_store(struct device *dev, struct device_attribute *attr, @@ -583,7 +719,6 @@ static ssize_t fan_mode_store(struct device *dev, struct device_attribute *attr, { u8 wdata; int result; -// int result = -EINVAL; result = kstrtou8(buf, 10, &wdata); if (result < 0) @@ -596,18 +731,6 @@ static ssize_t fan_mode_store(struct device *dev, struct device_attribute *attr, conf->fan_mode.mode_values[wdata]); } -// if (streq(buf, "auto")) -// result = -// ec_write(MSI_EC_FAN_MODE_ADDRESS, MSI_EC_FAN_MODE_AUTO); -// -// if (streq(buf, "basic")) -// result = ec_write(MSI_EC_FAN_MODE_ADDRESS, -// MSI_EC_FAN_MODE_BASIC); -// -// if (streq(buf, "advanced")) -// result = ec_write(MSI_EC_FAN_MODE_ADDRESS, -// MSI_EC_FAN_MODE_ADVANCED); - if (result < 0) return result; @@ -659,6 +782,8 @@ static DEVICE_ATTR_RW(webcam); static DEVICE_ATTR_RW(fn_key); static DEVICE_ATTR_RW(win_key); static DEVICE_ATTR_RW(battery_mode); +static DEVICE_ATTR_RO(lid_status); +static DEVICE_ATTR_RO(ac_connected); static DEVICE_ATTR_RW(cooler_boost); static DEVICE_ATTR_RW(shift_mode); static DEVICE_ATTR_RW(fan_mode); @@ -668,6 +793,7 @@ static DEVICE_ATTR_RO(fw_release_date); static struct attribute *msi_root_attrs[] = { &dev_attr_webcam.attr, &dev_attr_fn_key.attr, &dev_attr_win_key.attr, &dev_attr_battery_mode.attr, + &dev_attr_lid_status.attr, &dev_attr_ac_connected.attr, &dev_attr_cooler_boost.attr, &dev_attr_shift_mode.attr, &dev_attr_fan_mode.attr, &dev_attr_fw_version.attr, &dev_attr_fw_release_date.attr, NULL, @@ -982,6 +1108,29 @@ static int __init msi_ec_init(void) return -ENODEV; } + // get firmware version + u8 fw_version[MSI_EC_FW_VERSION_LENGTH + 1]; + result = ec_get_firmware_version_common_address(fw_version); + if (result < 0) { + return result; + } + + // check if this firmware's configuration is implemented + bool allowed = false; + for (int i = 0; CONFIGURATIONS[i]; i++) { + for (int j = 0; CONFIGURATIONS[i]->allowed_fw[j]; j++) { + if (strcmp(CONFIGURATIONS[i]->allowed_fw[j], fw_version) == 0) { + allowed = true; + conf = CONFIGURATIONS[i]; + break; + } + } + } + if (!allowed) { + pr_err("Your firmware version is not supported!\n"); + return -EOPNOTSUPP; + } + result = platform_driver_register(&msi_platform_driver); if (result < 0) { return result; diff --git a/registers_configuration.h b/registers_configuration.h index 55f8a3c..a7f74cb 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -5,6 +5,24 @@ #define MSI_DRIVER_NAME "msi-ec" +#define MSI_EC_CHARGING_STATUS_NOT_CHARGING 0x01 +#define MSI_EC_CHARGING_STATUS_CHARGING 0x03 +#define MSI_EC_CHARGING_STATUS_DISCHARGING 0x05 +#define MSI_EC_CHARGING_STATUS_FULL 0x09 +#define MSI_EC_CHARGING_STATUS_FULL_NO_POWER 0x0D +struct msi_ec_battery_info_conf { + int charge_percentage_address; + int charging_status_address; +}; + +struct msi_ec_charge_control_conf { + int address; + int offset_start; + int offset_end; + int range_min; + int range_max; +}; + struct msi_ec_webcam_conf { int address; int hard_address; @@ -27,11 +45,6 @@ struct msi_ec_power_status_conf { int ac_connected_bit; }; -struct msi_ec_charge_conf { - int battery_charge_address; - int charging_status_address; -}; - struct msi_ec_cooler_boost_conf { int address; int bit; @@ -44,24 +57,22 @@ struct msi_ec_shift_mode_conf { int max_mode; }; +struct msi_ec_fan_mode_conf { + int address; + int mode_values[4]; + int max_mode; +}; + +#define MSI_EC_FW_VERSION_ADDRESS 0xa0 #define MSI_EC_FW_VERSION_LENGTH 12 #define MSI_EC_FW_DATE_LENGTH 8 #define MSI_EC_FW_TIME_LENGTH 8 - struct msi_ec_fw_conf { int version_address; int date_address; int time_address; }; -struct msi_ec_charge_control_conf { - int address; - int offset_start; - int offset_end; - int range_min; - int range_max; -}; - struct msi_ec_cpu_conf { int rt_temp_address; int rt_fan_speed_address; // realtime @@ -77,16 +88,9 @@ struct msi_ec_gpu_conf { int rt_fan_speed_address; // realtime }; -struct msi_ec_fan_mode_conf { - int address; - int mode_values[4]; - int max_mode; -}; - struct msi_ec_led_conf { int micmute_led_address; int mute_led_address; - int base_value; int bit; }; @@ -102,103 +106,22 @@ struct msi_ec_kbd_bl_conf { }; struct msi_ec_conf { + const char **allowed_fw; + + struct msi_ec_battery_info_conf battery_info; + struct msi_ec_charge_control_conf charge_control; struct msi_ec_webcam_conf webcam; struct msi_ec_fn_win_swap_conf fn_win_swap; struct msi_ec_battery_mode_conf battery_mode; struct msi_ec_power_status_conf power_status; - struct msi_ec_charge_conf charge; struct msi_ec_cooler_boost_conf cooler_boost; struct msi_ec_shift_mode_conf shift_mode; + struct msi_ec_fan_mode_conf fan_mode; struct msi_ec_fw_conf fw; - struct msi_ec_charge_control_conf charge_control; struct msi_ec_cpu_conf cpu; struct msi_ec_gpu_conf gpu; - struct msi_ec_fan_mode_conf fan_mode; struct msi_ec_led_conf leds; struct msi_ec_kbd_bl_conf kbd_bl; }; -static struct msi_ec_conf CONFIGURATIONS[1] = { - { - .webcam = { - .address = 0x2e, - .hard_address = 0x2f, - .bit = 1, - }, - .fn_win_swap = { - .address = 0xbf, - .bit = 4, - }, - .battery_mode = { - .address = 0xef, - .modes = { 0xbc, 0xd0, 0xe4 }, - }, - .power_status = { - .address = 0x30, - .lid_open_bit = 1, - .ac_connected_bit = 0, - }, - .charge = { - .battery_charge_address = 0x42, - .charging_status_address = 0x31, - }, - .cooler_boost = { - .address = 0x98, - .bit = 7, - }, - .shift_mode = { - .address = 0xf2, - .off_value = 0x80, - .base_value = 0xc0, - .max_mode = 4, - }, - .fw = { - .version_address = 0xa0, - .date_address = 0xac, - .time_address = 0xb4, - }, - .charge_control = { - .address = 0xef, - .offset_start = 0x8a, - .offset_end = 0x80, - .range_min = 0x8a, - .range_max = 0xe4, - }, - .cpu = { - .rt_temp_address = 0x68, - .rt_fan_speed_address = 0x71, - .rt_fan_speed_base_min = 0x19, - .rt_fan_speed_base_max = 0x37, - .bs_fan_speed_address = 0x89, - .bs_fan_speed_base_min = 0x00, - .bs_fan_speed_base_max = 0x0f, - }, - .gpu = { - .rt_temp_address = 0x80, - .rt_fan_speed_address = 0x89, - }, - .fan_mode = { - .address = 0xf4, - .mode_values = { 0x0d, 0x1d, 0x4d, 0x8d }, - .max_mode = 3, - }, - .leds = { - .micmute_led_address = 0x2b, - .mute_led_address = 0x2c, - .base_value = 0x80, - .bit = 2, - }, - .kbd_bl = { - .bl_mode_address = 0x2c, // ? - .bl_modes = { 0x00, 0x08 }, // ? - .max_mode = 1, // ? - .bl_state_address = 0xf3, - .state_base_value = 0x80, - .max_state = 3, - }, - }, -}; - -static struct msi_ec_conf *conf = CONFIGURATIONS + 0; // current configuration - #endif // __MSI_EC_CONSTANTS__ From 7e92bdc4f7dc987d47cc80fe883f8d4fb98d4144 Mon Sep 17 00:00:00 2001 From: teackot Date: Thu, 5 Jan 2023 23:30:17 +0300 Subject: [PATCH 05/28] Use standardized properties names --- msi-ec.c | 30 +++++++++++++++--------------- registers_configuration.h | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index 5b02727..7d0a8ff 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -51,7 +51,7 @@ static const char *ALLOWED_FW_0[] = { static struct msi_ec_conf CONF0 = { .allowed_fw = ALLOWED_FW_0, .battery_info = { - .charge_percentage_address = 0x42, + .capacity_address = 0x42, .charging_status_address = 0x31, }, .charge_control = { @@ -135,7 +135,7 @@ static const char *ALLOWED_FW_1[] = { static struct msi_ec_conf CONF1 = { .allowed_fw = ALLOWED_FW_1, .battery_info = { - .charge_percentage_address = 0x42, + .capacity_address = 0x42, .charging_status_address = 0x31, }, .charge_control = { @@ -296,23 +296,23 @@ static int ec_get_firmware_version_common_address(u8 buf[MSI_EC_FW_VERSION_LENGT // Sysfs power_supply subsystem // ============================================================ // -static ssize_t charge_percentage_show(struct device *device, - struct device_attribute *attr, - char *buf) +static ssize_t capacity_show(struct device *device, + struct device_attribute *attr, + char *buf) { u8 rdata; int result; - result = ec_read(conf->battery_info.charge_percentage_address, &rdata); + result = ec_read(conf->battery_info.capacity_address, &rdata); if (result < 0) return result; return sprintf(buf, "%i\n", rdata - 1); } -static ssize_t charging_status_show(struct device *device, - struct device_attribute *attr, - char *buf) +static ssize_t status_show(struct device *device, + struct device_attribute *attr, + char *buf) { u8 rdata; int result; @@ -331,9 +331,9 @@ static ssize_t charging_status_show(struct device *device, case MSI_EC_CHARGING_STATUS_FULL: return sprintf(buf, "%s\n", "Full"); case MSI_EC_CHARGING_STATUS_FULL_NO_POWER: - return sprintf(buf, "%s\n", "Full (no power)"); + return sprintf(buf, "%s\n", "Full"); default: - return sprintf(buf, "%s (%i)\n", "unknown", rdata); + return sprintf(buf, "%s (%i)\n", "Unknown", rdata); } } @@ -407,14 +407,14 @@ static ssize_t charge_control_end_threshold_store(struct device *dev, dev, attr, buf, count); } -static DEVICE_ATTR_RO(charge_percentage); -static DEVICE_ATTR_RO(charging_status); +static DEVICE_ATTR_RO(capacity); +static DEVICE_ATTR_RO(status); static DEVICE_ATTR_RW(charge_control_start_threshold); static DEVICE_ATTR_RW(charge_control_end_threshold); static struct attribute *msi_battery_attrs[] = { - &dev_attr_charge_percentage.attr, - &dev_attr_charging_status.attr, + &dev_attr_capacity.attr, + &dev_attr_status.attr, &dev_attr_charge_control_start_threshold.attr, &dev_attr_charge_control_end_threshold.attr, NULL, diff --git a/registers_configuration.h b/registers_configuration.h index a7f74cb..b2c1724 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -11,7 +11,7 @@ #define MSI_EC_CHARGING_STATUS_FULL 0x09 #define MSI_EC_CHARGING_STATUS_FULL_NO_POWER 0x0D struct msi_ec_battery_info_conf { - int charge_percentage_address; + int capacity_address; int charging_status_address; }; From a525addd5398c5f915af3f6dfb3d06c4f72f30f7 Mon Sep 17 00:00:00 2001 From: teackot Date: Sat, 7 Jan 2023 18:25:57 +0300 Subject: [PATCH 06/28] Remove capacity and status as they are already supported --- msi-ec.c | 53 --------------------------------------- registers_configuration.h | 11 -------- 2 files changed, 64 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index 7d0a8ff..4108063 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -50,10 +50,6 @@ static const char *ALLOWED_FW_0[] = { static struct msi_ec_conf CONF0 = { .allowed_fw = ALLOWED_FW_0, - .battery_info = { - .capacity_address = 0x42, - .charging_status_address = 0x31, - }, .charge_control = { .address = 0xef, .offset_start = 0x8a, @@ -134,10 +130,6 @@ static const char *ALLOWED_FW_1[] = { static struct msi_ec_conf CONF1 = { .allowed_fw = ALLOWED_FW_1, - .battery_info = { - .capacity_address = 0x42, - .charging_status_address = 0x31, - }, .charge_control = { .address = 0xd7, .offset_start = 0x8a, @@ -296,47 +288,6 @@ static int ec_get_firmware_version_common_address(u8 buf[MSI_EC_FW_VERSION_LENGT // Sysfs power_supply subsystem // ============================================================ // -static ssize_t capacity_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - u8 rdata; - int result; - - result = ec_read(conf->battery_info.capacity_address, &rdata); - if (result < 0) - return result; - - return sprintf(buf, "%i\n", rdata - 1); -} - -static ssize_t status_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - u8 rdata; - int result; - - result = ec_read(conf->battery_info.charging_status_address, &rdata); - if (result < 0) - return result; - - switch (rdata) { - case MSI_EC_CHARGING_STATUS_NOT_CHARGING: - return sprintf(buf, "%s\n", "Not charging"); - case MSI_EC_CHARGING_STATUS_CHARGING: - return sprintf(buf, "%s\n", "Charging"); - case MSI_EC_CHARGING_STATUS_DISCHARGING: - return sprintf(buf, "%s\n", "Discharging"); - case MSI_EC_CHARGING_STATUS_FULL: - return sprintf(buf, "%s\n", "Full"); - case MSI_EC_CHARGING_STATUS_FULL_NO_POWER: - return sprintf(buf, "%s\n", "Full"); - default: - return sprintf(buf, "%s (%i)\n", "Unknown", rdata); - } -} - static ssize_t charge_control_threshold_show(u8 offset, struct device *device, struct device_attribute *attr, char *buf) @@ -407,14 +358,10 @@ static ssize_t charge_control_end_threshold_store(struct device *dev, dev, attr, buf, count); } -static DEVICE_ATTR_RO(capacity); -static DEVICE_ATTR_RO(status); static DEVICE_ATTR_RW(charge_control_start_threshold); static DEVICE_ATTR_RW(charge_control_end_threshold); static struct attribute *msi_battery_attrs[] = { - &dev_attr_capacity.attr, - &dev_attr_status.attr, &dev_attr_charge_control_start_threshold.attr, &dev_attr_charge_control_end_threshold.attr, NULL, diff --git a/registers_configuration.h b/registers_configuration.h index b2c1724..6920249 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -5,16 +5,6 @@ #define MSI_DRIVER_NAME "msi-ec" -#define MSI_EC_CHARGING_STATUS_NOT_CHARGING 0x01 -#define MSI_EC_CHARGING_STATUS_CHARGING 0x03 -#define MSI_EC_CHARGING_STATUS_DISCHARGING 0x05 -#define MSI_EC_CHARGING_STATUS_FULL 0x09 -#define MSI_EC_CHARGING_STATUS_FULL_NO_POWER 0x0D -struct msi_ec_battery_info_conf { - int capacity_address; - int charging_status_address; -}; - struct msi_ec_charge_control_conf { int address; int offset_start; @@ -108,7 +98,6 @@ struct msi_ec_kbd_bl_conf { struct msi_ec_conf { const char **allowed_fw; - struct msi_ec_battery_info_conf battery_info; struct msi_ec_charge_control_conf charge_control; struct msi_ec_webcam_conf webcam; struct msi_ec_fn_win_swap_conf fn_win_swap; From efc7a3bb8d38979645d4579c1d434006a59bbfcd Mon Sep 17 00:00:00 2001 From: teackot Date: Sun, 8 Jan 2023 04:01:32 +0300 Subject: [PATCH 07/28] Human readable shift modes --- msi-ec.c | 92 +++++++++++++++++++++++++-------------- registers_configuration.h | 12 +++-- 2 files changed, 68 insertions(+), 36 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index 4108063..eaca306 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -42,6 +42,13 @@ #include #include +static const char *const SM_OFF_NAME = "off"; +static const char *const SM_ECO_NAME = "eco"; +static const char *const SM_COMFORT_NAME = "comfort"; +static const char *const SM_SPORT_NAME = "sport"; +static const char *const SM_TURBO_NAME = "turbo"; +static const char *const SM_OVERCLOCK_NAME = "overclock"; + static const char *ALLOWED_FW_0[] = { "14C1EMS1.101", "17F2EMS1.106", @@ -80,10 +87,15 @@ static struct msi_ec_conf CONF0 = { .bit = 7, }, .shift_mode = { - .address = 0xf2, - .off_value = 0x80, - .base_value = 0xc0, - .max_mode = 4, + .address = 0xf2, + .modes = { + { SM_OFF_NAME, 0x80 }, + { SM_ECO_NAME, 0xc2 }, + { SM_COMFORT_NAME, 0xc1 }, + { SM_SPORT_NAME, 0xc0 }, + { SM_TURBO_NAME, 0xc4 }, + }, + .modes_number = 5, }, .fan_mode = { .address = 0xf4, @@ -160,10 +172,14 @@ static struct msi_ec_conf CONF1 = { .bit = 7, }, .shift_mode = { - .address = 0xf2, - .off_value = 0x80, - .base_value = 0xc0, - .max_mode = 2, + .address = 0xf2, + .modes = { + { SM_OFF_NAME, 0x80 }, + { SM_ECO_NAME, 0xc2 }, + { SM_COMFORT_NAME, 0xc1 }, + { SM_OVERCLOCK_NAME, 0xc0 }, + }, + .modes_number = 4, }, .fan_mode = { .address = 0xd4, @@ -217,6 +233,24 @@ static struct msi_ec_conf *conf = &CONF0; // current configuration #define unset_bit(v, b) (v &= ~(1 << b)) #define check_bit(v, b) ((bool)((v >> b) & 1)) +// compares two, trimming newline at the end the second +static int strcmp_trim_newline2(const char *s, const char *s_nl) +{ + size_t s_nl_length = strlen(s_nl); + + if (s_nl_length - 1 > MSI_EC_SHIFT_MODE_NAME_LIMIT) + return -1; + + if (s_nl[s_nl_length - 1] == '\n') { + char s2[MSI_EC_SHIFT_MODE_NAME_LIMIT + 1]; + memcpy(s2, s_nl, s_nl_length - 1); + s2[s_nl_length - 1] = '\0'; + return strcmp(s, s2); + } + + return strcmp(s, s_nl); +} + static int ec_read_seq(u8 addr, u8 *buf, int len) { int result; @@ -595,7 +629,8 @@ static ssize_t cooler_boost_store(struct device *dev, } static ssize_t shift_mode_show(struct device *device, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { u8 rdata; int result; @@ -604,42 +639,33 @@ static ssize_t shift_mode_show(struct device *device, if (result < 0) return result; - if (rdata == conf->shift_mode.off_value) - return sprintf(buf, "-1\n"); - - unsigned int mode = rdata - conf->shift_mode.base_value; - if (mode > conf->shift_mode.max_mode) - return sprintf(buf, "%s (%i)\n", "unknown", rdata); + for (int i = 0; i < conf->shift_mode.modes_number; i++) { + if (rdata == conf->shift_mode.modes[i].value) { + return sprintf(buf, "%s\n", conf->shift_mode.modes[i].name); + } + } - return sprintf(buf, "%i\n", mode); + return sprintf(buf, "%s (%i)\n", "unknown", rdata); } static ssize_t shift_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int wdata; int result; - result = kstrtoint(buf, 10, &wdata); - if (result < 0) - return result; - - if (wdata == -1) { // off - result = ec_write(conf->shift_mode.address, - conf->shift_mode.off_value); - } else { // on (or invalid) - if ((unsigned int)wdata > conf->shift_mode.max_mode) - return -EINVAL; + for (int i = 0; i < conf->shift_mode.modes_number; i++) { + if (strcmp_trim_newline2(conf->shift_mode.modes[i].name, buf) == 0) { + result = ec_write(conf->shift_mode.address, + conf->shift_mode.modes[i].value); + if (result < 0) + return result; - result = ec_write(conf->shift_mode.address, - wdata + conf->shift_mode.base_value); + return count; + } } - if (result < 0) - return result; - - return count; + return -EINVAL; } static ssize_t fan_mode_show(struct device *device, diff --git a/registers_configuration.h b/registers_configuration.h index 6920249..a5b4e16 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -40,11 +40,17 @@ struct msi_ec_cooler_boost_conf { int bit; }; +#define MSI_EC_SHIFT_MODE_NAME_LIMIT 20 + +struct msi_ec_shift_mode { + const char *name; + int value; +}; + struct msi_ec_shift_mode_conf { int address; - int off_value; - int base_value; - int max_mode; + struct msi_ec_shift_mode modes[5]; // fixed size for easier hard coding + int modes_number; }; struct msi_ec_fan_mode_conf { From b7190b49dcdc0b6adfd1e4c3507bcb5594b08f19 Mon Sep 17 00:00:00 2001 From: teackot Date: Sun, 8 Jan 2023 04:57:44 +0300 Subject: [PATCH 08/28] Attribute reporting all available shift modes --- README.md | 15 ++++++++----- msi-ec.c | 45 ++++++++++++++++++++++++++++++--------- registers_configuration.h | 2 +- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 8778115..4afe9d7 100644 --- a/README.md +++ b/README.md @@ -66,12 +66,17 @@ This driver exports a few files in its own platform device, msi-ec, and is avail - `/sys/devices/platform/msi-ec/shift_mode` - Description: This entry allows switching the shift mode. It provides a set of profiles for gaining CPU & GPU overclock/underclock. - Access: Read, Write - - Valid values: - - turbo: over-voltage and over-clock for the CPU & GPU, aka overcloking mode - - sport: full clock frequency for the CPU & GPU, aka default desktop mode - - comfort: dynamic clock frequency for the CPU & GPU, aka power balanced mode + - Valid values: Values reported by `/sys/devices/platform/msi-ec/available_shift_modes`. Some of the possible values: + - off (necessary): operating system decides - eco: low clock frequency for the CPU & GPU, aka power saving mode - - off: operating system decides + - comfort: dynamic clock frequency for the CPU & GPU, aka power balanced mode + - sport: full clock frequency for the CPU & GPU, aka default desktop mode + - turbo: over-voltage and over-clock for the CPU & GPU, aka overclocking mode + +- `/sys/devices/platform/msi-ec/available_shift_modes` + - Description: This entry reports all supported shift modes. + - Access: Read + - Valid values: Newline separated list of strings. - `/sys/devices/platform/msi-ec/fan_mode` - Description: This entry allows switching the fan mode. It provides a set of profiles for adjusting the fan speed under specific criteria. diff --git a/msi-ec.c b/msi-ec.c index eaca306..dc31c1f 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -95,7 +95,7 @@ static struct msi_ec_conf CONF0 = { { SM_SPORT_NAME, 0xc0 }, { SM_TURBO_NAME, 0xc4 }, }, - .modes_number = 5, + .modes_count = 5, }, .fan_mode = { .address = 0xf4, @@ -179,7 +179,7 @@ static struct msi_ec_conf CONF1 = { { SM_COMFORT_NAME, 0xc1 }, { SM_OVERCLOCK_NAME, 0xc0 }, }, - .modes_number = 4, + .modes_count = 4, }, .fan_mode = { .address = 0xd4, @@ -628,6 +628,23 @@ static ssize_t cooler_boost_store(struct device *dev, return count; } +static ssize_t available_shift_modes_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + int result = 0; + int count = 0; + + for (int i = 0; i < conf->shift_mode.modes_count; i++) { + result = sprintf(buf + count, "%s\n", conf->shift_mode.modes[i].name); + if (result < 0) + return result; + count += result; + } + + return count; +} + static ssize_t shift_mode_show(struct device *device, struct device_attribute *attr, char *buf) @@ -639,7 +656,7 @@ static ssize_t shift_mode_show(struct device *device, if (result < 0) return result; - for (int i = 0; i < conf->shift_mode.modes_number; i++) { + for (int i = 0; i < conf->shift_mode.modes_count; i++) { if (rdata == conf->shift_mode.modes[i].value) { return sprintf(buf, "%s\n", conf->shift_mode.modes[i].name); } @@ -654,7 +671,7 @@ static ssize_t shift_mode_store(struct device *dev, { int result; - for (int i = 0; i < conf->shift_mode.modes_number; i++) { + for (int i = 0; i < conf->shift_mode.modes_count; i++) { if (strcmp_trim_newline2(conf->shift_mode.modes[i].name, buf) == 0) { result = ec_write(conf->shift_mode.address, conf->shift_mode.modes[i].value); @@ -758,18 +775,26 @@ static DEVICE_ATTR_RW(battery_mode); static DEVICE_ATTR_RO(lid_status); static DEVICE_ATTR_RO(ac_connected); static DEVICE_ATTR_RW(cooler_boost); +static DEVICE_ATTR_RO(available_shift_modes); static DEVICE_ATTR_RW(shift_mode); static DEVICE_ATTR_RW(fan_mode); static DEVICE_ATTR_RO(fw_version); static DEVICE_ATTR_RO(fw_release_date); static struct attribute *msi_root_attrs[] = { - &dev_attr_webcam.attr, &dev_attr_fn_key.attr, - &dev_attr_win_key.attr, &dev_attr_battery_mode.attr, - &dev_attr_lid_status.attr, &dev_attr_ac_connected.attr, - &dev_attr_cooler_boost.attr, &dev_attr_shift_mode.attr, - &dev_attr_fan_mode.attr, &dev_attr_fw_version.attr, - &dev_attr_fw_release_date.attr, NULL, + &dev_attr_webcam.attr, + &dev_attr_fn_key.attr, + &dev_attr_win_key.attr, + &dev_attr_battery_mode.attr, + &dev_attr_lid_status.attr, + &dev_attr_ac_connected.attr, + &dev_attr_cooler_boost.attr, + &dev_attr_available_shift_modes.attr, + &dev_attr_shift_mode.attr, + &dev_attr_fan_mode.attr, + &dev_attr_fw_version.attr, + &dev_attr_fw_release_date.attr, + NULL, }; static const struct attribute_group msi_root_group = { diff --git a/registers_configuration.h b/registers_configuration.h index a5b4e16..91efa7d 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -50,7 +50,7 @@ struct msi_ec_shift_mode { struct msi_ec_shift_mode_conf { int address; struct msi_ec_shift_mode modes[5]; // fixed size for easier hard coding - int modes_number; + int modes_count; }; struct msi_ec_fan_mode_conf { From ef7b1278f147f2b0af5427dd3a6a8c15c7af94f0 Mon Sep 17 00:00:00 2001 From: teackot Date: Sun, 8 Jan 2023 17:00:05 +0300 Subject: [PATCH 09/28] Human readable fan modes --- msi-ec.c | 57 ++++++++++++++++++++------------------- registers_configuration.h | 9 +++---- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index dc31c1f..e2e7ca8 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -42,11 +42,11 @@ #include #include -static const char *const SM_OFF_NAME = "off"; -static const char *const SM_ECO_NAME = "eco"; -static const char *const SM_COMFORT_NAME = "comfort"; -static const char *const SM_SPORT_NAME = "sport"; -static const char *const SM_TURBO_NAME = "turbo"; +static const char *const SM_OFF_NAME = "off"; +static const char *const SM_ECO_NAME = "eco"; +static const char *const SM_COMFORT_NAME = "comfort"; +static const char *const SM_SPORT_NAME = "sport"; +static const char *const SM_TURBO_NAME = "turbo"; static const char *const SM_OVERCLOCK_NAME = "overclock"; static const char *ALLOWED_FW_0[] = { @@ -98,9 +98,7 @@ static struct msi_ec_conf CONF0 = { .modes_count = 5, }, .fan_mode = { - .address = 0xf4, - .mode_values = { 0x0d, 0x4d, 0x8d }, - .max_mode = 2, + .address = 0xf4, }, .fw = { .version_address = 0xa0, @@ -182,9 +180,7 @@ static struct msi_ec_conf CONF1 = { .modes_count = 4, }, .fan_mode = { - .address = 0xd4, - .mode_values = { 0x1d, 0x4d, 0x8d }, - .max_mode = 2, + .address = 0xd4, }, .fw = { .version_address = 0xa0, @@ -227,6 +223,18 @@ static struct msi_ec_conf *CONFIGURATIONS[] = { static struct msi_ec_conf *conf = &CONF0; // current configuration +#define FAN_MODES_COUNT 4 +static const char *const FM_AUTO_NAME = "auto"; +static const char *const FM_SILENT_NAME = "silent"; +static const char *const FM_BASIC_NAME = "basic"; +static const char *const FM_ADVANCED_NAME = "advanced"; +static const struct msi_ec_mode FAN_MODES[] = { + { FM_AUTO_NAME, 0x0d }, + { FM_SILENT_NAME, 0x1d }, + { FM_BASIC_NAME, 0x4d }, + { FM_ADVANCED_NAME, 0x8d } +}; + #define streq(x, y) (strcmp(x, y) == 0 || strcmp(x, y "\n") == 0) #define set_bit(v, b) (v |= (1 << b)) @@ -695,9 +703,9 @@ static ssize_t fan_mode_show(struct device *device, if (result < 0) return result; - for (int i = 0; i <= conf->fan_mode.max_mode; i++) { - if (rdata == conf->fan_mode.mode_values[i]) { - return sprintf(buf, "%i\n", i); + for (int i = 0; i < FAN_MODES_COUNT; i++) { + if (rdata == FAN_MODES[i].value) { + return sprintf(buf, "%s\n", FAN_MODES[i].name); } } @@ -707,24 +715,19 @@ static ssize_t fan_mode_show(struct device *device, static ssize_t fan_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - u8 wdata; int result; - result = kstrtou8(buf, 10, &wdata); - if (result < 0) - return result; + for (int i = 0; i < FAN_MODES_COUNT; i++) { + if (strcmp_trim_newline2(FAN_MODES[i].name, buf) == 0) { + result = ec_write(conf->fan_mode.address, FAN_MODES[i].value); + if (result < 0) + return result; - if (wdata > conf->fan_mode.max_mode) { - result = -EINVAL; - } else { - result = ec_write(conf->fan_mode.address, - conf->fan_mode.mode_values[wdata]); + return count; + } } - if (result < 0) - return result; - - return count; + return -EINVAL; } static ssize_t fw_version_show(struct device *device, diff --git a/registers_configuration.h b/registers_configuration.h index 91efa7d..ecfc0dc 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -40,23 +40,20 @@ struct msi_ec_cooler_boost_conf { int bit; }; -#define MSI_EC_SHIFT_MODE_NAME_LIMIT 20 - -struct msi_ec_shift_mode { +struct msi_ec_mode { const char *name; int value; }; +#define MSI_EC_SHIFT_MODE_NAME_LIMIT 20 struct msi_ec_shift_mode_conf { int address; - struct msi_ec_shift_mode modes[5]; // fixed size for easier hard coding + struct msi_ec_mode modes[5]; // fixed size for easier hard coding int modes_count; }; struct msi_ec_fan_mode_conf { int address; - int mode_values[4]; - int max_mode; }; #define MSI_EC_FW_VERSION_ADDRESS 0xa0 From edf57a3ea7abd7cdf2b677b9af022785ac2c114d Mon Sep 17 00:00:00 2001 From: teackot Date: Sun, 8 Jan 2023 20:22:39 +0300 Subject: [PATCH 10/28] Added a configuration for two new firmwares (#10) --- msi-ec.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/msi-ec.c b/msi-ec.c index e2e7ca8..1b8c48a 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -215,9 +215,93 @@ static struct msi_ec_conf CONF1 = { }, }; +static const char *ALLOWED_FW_2[] = { + "1592EMS1.111", + "E1592IMS.10C", + NULL, +}; + +static struct msi_ec_conf CONF2 = { + .allowed_fw = ALLOWED_FW_2, + .charge_control = { + .address = 0xef, + .offset_start = 0x8a, + .offset_end = 0x80, + .range_min = 0x8a, + .range_max = 0xe4, + }, + .webcam = { + .address = 0x2e, + .hard_address = 0x2f, + .bit = 1, + }, + .fn_win_swap = { + .address = 0xe8, + .bit = 4, + }, + .battery_mode = { + .address = 0xef, + .modes = { 0xbc, 0xd0, 0xe4 }, + }, + .power_status = { + .address = 0x30, + .lid_open_bit = 1, + .ac_connected_bit = 0, + }, + .cooler_boost = { + .address = 0x98, + .bit = 7, + }, + .shift_mode = { + .address = 0xd2, + .modes = { + { SM_OFF_NAME, 0x80 }, + { SM_ECO_NAME, 0xc2 }, + { SM_COMFORT_NAME, 0xc1 }, + { SM_OVERCLOCK_NAME, 0xc0 }, + }, + .modes_count = 4, + }, + .fan_mode = { + .address = 0xd4, + }, + .fw = { + .version_address = 0xa0, + .date_address = 0xac, + .time_address = 0xb4, + }, + .cpu = { + .rt_temp_address = 0x68, + .rt_fan_speed_address = 0xc9, + .rt_fan_speed_base_min = 0x19, + .rt_fan_speed_base_max = 0x37, + .bs_fan_speed_address = 0x89, // ? + .bs_fan_speed_base_min = 0x00, + .bs_fan_speed_base_max = 0x0f, + }, + .gpu = { + .rt_temp_address = 0x80, + .rt_fan_speed_address = 0x89, + }, + .leds = { + .micmute_led_address = 0x2c, + .mute_led_address = 0x2d, + .bit = 1, + }, + .kbd_bl = { + .bl_mode_address = 0x2c, // ? + .bl_modes = { 0x00, 0x08 }, // ? + .max_mode = 1, // ? + .bl_state_address = 0xd3, + .state_base_value = 0x80, + .max_state = 3, + }, +}; + static struct msi_ec_conf *CONFIGURATIONS[] = { &CONF0, &CONF1, + &CONF2, NULL, }; From f76ae490362fc8f8ae36d242d1f208abee7f25db Mon Sep 17 00:00:00 2001 From: teackot Date: Mon, 9 Jan 2023 01:59:38 +0300 Subject: [PATCH 11/28] Corrected led config for E16 Flip --- msi-ec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index 1b8c48a..e5c59b8 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -284,8 +284,8 @@ static struct msi_ec_conf CONF2 = { .rt_fan_speed_address = 0x89, }, .leds = { - .micmute_led_address = 0x2c, - .mute_led_address = 0x2d, + .micmute_led_address = 0x2b, + .mute_led_address = 0x2c, .bit = 1, }, .kbd_bl = { From b815cb5c28f3f6aa505341c1f077a079e9940813 Mon Sep 17 00:00:00 2001 From: teackot Date: Sun, 15 Jan 2023 00:01:36 +0300 Subject: [PATCH 12/28] Renamed a header in the dkms section of makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 36d42eb..7f67bf1 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ dkms-install: cp $(CURDIR)/dkms.conf $(DKMS_ROOT_PATH) cp $(CURDIR)/Makefile $(DKMS_ROOT_PATH) cp $(CURDIR)/msi-ec.c $(DKMS_ROOT_PATH) - cp $(CURDIR)/constants.h $(DKMS_ROOT_PATH) + cp $(CURDIR)/registers_configuration.h $(DKMS_ROOT_PATH) sed -e "s/@CFLGS@/${MCFLAGS}/" \ -e "s/@VERSION@/$(VERSION)/" \ From a09165da18519a2538a8150259280de1135b1042 Mon Sep 17 00:00:00 2001 From: teackot Date: Wed, 18 Jan 2023 01:10:11 +0300 Subject: [PATCH 13/28] Store configurations in the init section --- msi-ec.c | 168 +++++++++++++++++++++++++++---------------------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index e5c59b8..faca1ca 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -55,7 +55,7 @@ static const char *ALLOWED_FW_0[] = { NULL, }; -static struct msi_ec_conf CONF0 = { +static struct msi_ec_conf CONF0 __initdata = { .allowed_fw = ALLOWED_FW_0, .charge_control = { .address = 0xef, @@ -138,7 +138,7 @@ static const char *ALLOWED_FW_1[] = { NULL, }; -static struct msi_ec_conf CONF1 = { +static struct msi_ec_conf CONF1 __initdata = { .allowed_fw = ALLOWED_FW_1, .charge_control = { .address = 0xd7, @@ -221,7 +221,7 @@ static const char *ALLOWED_FW_2[] = { NULL, }; -static struct msi_ec_conf CONF2 = { +static struct msi_ec_conf CONF2 __initdata = { .allowed_fw = ALLOWED_FW_2, .charge_control = { .address = 0xef, @@ -298,14 +298,14 @@ static struct msi_ec_conf CONF2 = { }, }; -static struct msi_ec_conf *CONFIGURATIONS[] = { +static struct msi_ec_conf *CONFIGURATIONS[] __initdata = { &CONF0, &CONF1, &CONF2, NULL, }; -static struct msi_ec_conf *conf = &CONF0; // current configuration +static struct msi_ec_conf conf; // current configuration #define FAN_MODES_COUNT 4 static const char *const FM_AUTO_NAME = "auto"; @@ -421,7 +421,7 @@ static ssize_t charge_control_threshold_show(u8 offset, struct device *device, u8 rdata; int result; - result = ec_read(conf->charge_control.address, &rdata); + result = ec_read(conf.charge_control.address, &rdata); if (result < 0) return result; @@ -432,7 +432,7 @@ static ssize_t charge_control_start_threshold_show(struct device *device, struct device_attribute *attr, char *buf) { - return charge_control_threshold_show(conf->charge_control.offset_start, + return charge_control_threshold_show(conf.charge_control.offset_start, device, attr, buf); } @@ -440,7 +440,7 @@ static ssize_t charge_control_end_threshold_show(struct device *device, struct device_attribute *attr, char *buf) { - return charge_control_threshold_show(conf->charge_control.offset_end, + return charge_control_threshold_show(conf.charge_control.offset_end, device, attr, buf); } @@ -456,11 +456,11 @@ static ssize_t charge_control_threshold_store(u8 offset, struct device *dev, return result; wdata += offset; - if (wdata < conf->charge_control.range_min || - wdata > conf->charge_control.range_max) + if (wdata < conf.charge_control.range_min || + wdata > conf.charge_control.range_max) return -EINVAL; - result = ec_write(conf->charge_control.address, wdata); + result = ec_write(conf.charge_control.address, wdata); if (result < 0) return result; @@ -473,14 +473,14 @@ charge_control_start_threshold_store(struct device *dev, const char *buf, size_t count) { return charge_control_threshold_store( - conf->charge_control.offset_start, dev, attr, buf, count); + conf.charge_control.offset_start, dev, attr, buf, count); } static ssize_t charge_control_end_threshold_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - return charge_control_threshold_store(conf->charge_control.offset_end, + return charge_control_threshold_store(conf.charge_control.offset_end, dev, attr, buf, count); } @@ -524,7 +524,7 @@ static ssize_t webcam_show(struct device *device, struct device_attribute *attr, int result; bool bit_value; - result = ec_check_bit(conf->webcam.address, conf->webcam.bit, &bit_value); + result = ec_check_bit(conf.webcam.address, conf.webcam.bit, &bit_value); if (bit_value) { return sprintf(buf, "%s\n", "on"); @@ -539,10 +539,10 @@ static ssize_t webcam_store(struct device *dev, struct device_attribute *attr, int result = -EINVAL; if (streq(buf, "on")) - result = ec_set_bit(conf->webcam.address, conf->webcam.bit); + result = ec_set_bit(conf.webcam.address, conf.webcam.bit); if (streq(buf, "off")) - result = ec_unset_bit(conf->webcam.address, conf->webcam.bit); + result = ec_unset_bit(conf.webcam.address, conf.webcam.bit); if (result < 0) return result; @@ -556,7 +556,7 @@ static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, int result; bool bit_value; - result = ec_check_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit, &bit_value); + result = ec_check_bit(conf.fn_win_swap.address, conf.fn_win_swap.bit, &bit_value); if (bit_value) { return sprintf(buf, "%s\n", "right"); @@ -571,9 +571,9 @@ static ssize_t fn_key_store(struct device *dev, struct device_attribute *attr, int result; if (streq(buf, "right")) { - result = ec_set_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit); + result = ec_set_bit(conf.fn_win_swap.address, conf.fn_win_swap.bit); } else if (streq(buf, "left")) { - result = ec_unset_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit); + result = ec_unset_bit(conf.fn_win_swap.address, conf.fn_win_swap.bit); } if (result < 0) @@ -588,7 +588,7 @@ static ssize_t win_key_show(struct device *device, int result; bool bit_value; - result = ec_check_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit, &bit_value); + result = ec_check_bit(conf.fn_win_swap.address, conf.fn_win_swap.bit, &bit_value); if (bit_value) { return sprintf(buf, "%s\n", "left"); @@ -603,9 +603,9 @@ static ssize_t win_key_store(struct device *dev, struct device_attribute *attr, int result; if (streq(buf, "right")) { - result = ec_unset_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit); + result = ec_unset_bit(conf.fn_win_swap.address, conf.fn_win_swap.bit); } else if (streq(buf, "left")) { - result = ec_set_bit(conf->fn_win_swap.address, conf->fn_win_swap.bit); + result = ec_set_bit(conf.fn_win_swap.address, conf.fn_win_swap.bit); } if (result < 0) @@ -620,15 +620,15 @@ static ssize_t battery_mode_show(struct device *device, u8 rdata; int result; - result = ec_read(conf->battery_mode.address, &rdata); + result = ec_read(conf.battery_mode.address, &rdata); if (result < 0) return result; - if (rdata == conf->battery_mode.modes[2]) { + if (rdata == conf.battery_mode.modes[2]) { return sprintf(buf, "%s\n", "max"); - } else if (rdata == conf->battery_mode.modes[1]) { + } else if (rdata == conf.battery_mode.modes[1]) { return sprintf(buf, "%s\n", "medium"); - } else if (rdata == conf->battery_mode.modes[0]) { + } else if (rdata == conf.battery_mode.modes[0]) { return sprintf(buf, "%s\n", "min"); } else { return sprintf(buf, "%s (%i)\n", "unknown", rdata); @@ -642,16 +642,16 @@ static ssize_t battery_mode_store(struct device *dev, int result = -EINVAL; if (streq(buf, "max")) - result = ec_write(conf->battery_mode.address, - conf->battery_mode.modes[2]); + result = ec_write(conf.battery_mode.address, + conf.battery_mode.modes[2]); else if (streq(buf, "medium")) - result = ec_write(conf->battery_mode.address, - conf->battery_mode.modes[1]); + result = ec_write(conf.battery_mode.address, + conf.battery_mode.modes[1]); else if (streq(buf, "min")) - result = ec_write(conf->battery_mode.address, - conf->battery_mode.modes[0]); + result = ec_write(conf.battery_mode.address, + conf.battery_mode.modes[0]); if (result < 0) return result; @@ -665,7 +665,7 @@ static ssize_t lid_status_show(struct device *device, int result; bool bit_value; - result = ec_check_bit(conf->power_status.address, conf->power_status.lid_open_bit, &bit_value); + result = ec_check_bit(conf.power_status.address, conf.power_status.lid_open_bit, &bit_value); if (result < 0) return result; @@ -678,7 +678,7 @@ static ssize_t ac_connected_show(struct device *device, int result; bool bit_value; - result = ec_check_bit(conf->power_status.address, conf->power_status.ac_connected_bit, &bit_value); + result = ec_check_bit(conf.power_status.address, conf.power_status.ac_connected_bit, &bit_value); if (result < 0) return result; @@ -691,7 +691,7 @@ static ssize_t cooler_boost_show(struct device *device, int result; bool bit_value; - result = ec_check_bit(conf->cooler_boost.address, conf->cooler_boost.bit, &bit_value); + result = ec_check_bit(conf.cooler_boost.address, conf.cooler_boost.bit, &bit_value); if (bit_value) { return sprintf(buf, "%s\n", "on"); @@ -707,12 +707,12 @@ static ssize_t cooler_boost_store(struct device *dev, int result = -EINVAL; if (streq(buf, "on")) - result = ec_set_bit(conf->cooler_boost.address, - conf->cooler_boost.bit); + result = ec_set_bit(conf.cooler_boost.address, + conf.cooler_boost.bit); else if (streq(buf, "off")) - result = ec_unset_bit(conf->cooler_boost.address, - conf->cooler_boost.bit); + result = ec_unset_bit(conf.cooler_boost.address, + conf.cooler_boost.bit); if (result < 0) return result; @@ -727,8 +727,8 @@ static ssize_t available_shift_modes_show(struct device *device, int result = 0; int count = 0; - for (int i = 0; i < conf->shift_mode.modes_count; i++) { - result = sprintf(buf + count, "%s\n", conf->shift_mode.modes[i].name); + for (int i = 0; i < conf.shift_mode.modes_count; i++) { + result = sprintf(buf + count, "%s\n", conf.shift_mode.modes[i].name); if (result < 0) return result; count += result; @@ -744,13 +744,13 @@ static ssize_t shift_mode_show(struct device *device, u8 rdata; int result; - result = ec_read(conf->shift_mode.address, &rdata); + result = ec_read(conf.shift_mode.address, &rdata); if (result < 0) return result; - for (int i = 0; i < conf->shift_mode.modes_count; i++) { - if (rdata == conf->shift_mode.modes[i].value) { - return sprintf(buf, "%s\n", conf->shift_mode.modes[i].name); + for (int i = 0; i < conf.shift_mode.modes_count; i++) { + if (rdata == conf.shift_mode.modes[i].value) { + return sprintf(buf, "%s\n", conf.shift_mode.modes[i].name); } } @@ -763,10 +763,10 @@ static ssize_t shift_mode_store(struct device *dev, { int result; - for (int i = 0; i < conf->shift_mode.modes_count; i++) { - if (strcmp_trim_newline2(conf->shift_mode.modes[i].name, buf) == 0) { - result = ec_write(conf->shift_mode.address, - conf->shift_mode.modes[i].value); + for (int i = 0; i < conf.shift_mode.modes_count; i++) { + if (strcmp_trim_newline2(conf.shift_mode.modes[i].name, buf) == 0) { + result = ec_write(conf.shift_mode.address, + conf.shift_mode.modes[i].value); if (result < 0) return result; @@ -783,7 +783,7 @@ static ssize_t fan_mode_show(struct device *device, u8 rdata; int result; - result = ec_read(conf->fan_mode.address, &rdata); + result = ec_read(conf.fan_mode.address, &rdata); if (result < 0) return result; @@ -803,7 +803,7 @@ static ssize_t fan_mode_store(struct device *dev, struct device_attribute *attr, for (int i = 0; i < FAN_MODES_COUNT; i++) { if (strcmp_trim_newline2(FAN_MODES[i].name, buf) == 0) { - result = ec_write(conf->fan_mode.address, FAN_MODES[i].value); + result = ec_write(conf.fan_mode.address, FAN_MODES[i].value); if (result < 0) return result; @@ -821,7 +821,7 @@ static ssize_t fw_version_show(struct device *device, int result; memset(rdata, 0, MSI_EC_FW_VERSION_LENGTH + 1); - result = ec_read_seq(conf->fw.version_address, rdata, + result = ec_read_seq(conf.fw.version_address, rdata, MSI_EC_FW_VERSION_LENGTH); if (result < 0) return result; @@ -838,14 +838,14 @@ static ssize_t fw_release_date_show(struct device *device, int year, month, day, hour, minute, second; memset(rdate, 0, MSI_EC_FW_DATE_LENGTH + 1); - result = ec_read_seq(conf->fw.date_address, rdate, + result = ec_read_seq(conf.fw.date_address, rdate, MSI_EC_FW_DATE_LENGTH); if (result < 0) return result; sscanf(rdate, "%02d%02d%04d", &month, &day, &year); memset(rtime, 0, MSI_EC_FW_TIME_LENGTH + 1); - result = ec_read_seq(conf->fw.time_address, rtime, + result = ec_read_seq(conf.fw.time_address, rtime, MSI_EC_FW_TIME_LENGTH); if (result < 0) return result; @@ -899,7 +899,7 @@ static ssize_t cpu_realtime_temperature_show(struct device *device, u8 rdata; int result; - result = ec_read(conf->cpu.rt_temp_address, &rdata); + result = ec_read(conf.cpu.rt_temp_address, &rdata); if (result < 0) return result; @@ -913,18 +913,18 @@ static ssize_t cpu_realtime_fan_speed_show(struct device *device, u8 rdata; int result; - result = ec_read(conf->cpu.rt_fan_speed_address, &rdata); + result = ec_read(conf.cpu.rt_fan_speed_address, &rdata); if (result < 0) return result; - if ((rdata < conf->cpu.rt_fan_speed_base_min || - rdata > conf->cpu.rt_fan_speed_base_max)) + if ((rdata < conf.cpu.rt_fan_speed_base_min || + rdata > conf.cpu.rt_fan_speed_base_max)) return -EINVAL; return sprintf(buf, "%i\n", - 100 * (rdata - conf->cpu.rt_fan_speed_base_min) / - (conf->cpu.rt_fan_speed_base_max - - conf->cpu.rt_fan_speed_base_min)); + 100 * (rdata - conf.cpu.rt_fan_speed_base_min) / + (conf.cpu.rt_fan_speed_base_max - + conf.cpu.rt_fan_speed_base_min)); } static ssize_t cpu_basic_fan_speed_show(struct device *device, @@ -934,18 +934,18 @@ static ssize_t cpu_basic_fan_speed_show(struct device *device, u8 rdata; int result; - result = ec_read(conf->cpu.bs_fan_speed_address, &rdata); + result = ec_read(conf.cpu.bs_fan_speed_address, &rdata); if (result < 0) return result; - if (rdata < conf->cpu.bs_fan_speed_base_min || - rdata > conf->cpu.bs_fan_speed_base_max) + if (rdata < conf.cpu.bs_fan_speed_base_min || + rdata > conf.cpu.bs_fan_speed_base_max) return -EINVAL; return sprintf(buf, "%i\n", - 100 * (rdata - conf->cpu.bs_fan_speed_base_min) / - (conf->cpu.bs_fan_speed_base_max - - conf->cpu.bs_fan_speed_base_min)); + 100 * (rdata - conf.cpu.bs_fan_speed_base_min) / + (conf.cpu.bs_fan_speed_base_max - + conf.cpu.bs_fan_speed_base_min)); } static ssize_t cpu_basic_fan_speed_store(struct device *dev, @@ -962,10 +962,10 @@ static ssize_t cpu_basic_fan_speed_store(struct device *dev, if (wdata > 100) return -EINVAL; - result = ec_write(conf->cpu.bs_fan_speed_address, - (wdata * (conf->cpu.bs_fan_speed_base_max - - conf->cpu.bs_fan_speed_base_min) + - 100 * conf->cpu.bs_fan_speed_base_min) / + result = ec_write(conf.cpu.bs_fan_speed_address, + (wdata * (conf.cpu.bs_fan_speed_base_max - + conf.cpu.bs_fan_speed_base_min) + + 100 * conf.cpu.bs_fan_speed_base_min) / 100); if (result < 0) return result; @@ -1021,7 +1021,7 @@ static ssize_t gpu_realtime_temperature_show(struct device *device, u8 rdata; int result; - result = ec_read(conf->gpu.rt_temp_address, &rdata); + result = ec_read(conf.gpu.rt_temp_address, &rdata); if (result < 0) return result; @@ -1035,7 +1035,7 @@ static ssize_t gpu_realtime_fan_speed_show(struct device *device, u8 rdata; int result; - result = ec_read(conf->gpu.rt_fan_speed_address, &rdata); + result = ec_read(conf.gpu.rt_fan_speed_address, &rdata); if (result < 0) return result; @@ -1111,9 +1111,9 @@ static int micmute_led_sysfs_set(struct led_classdev *led_cdev, int result; if (brightness) { - result = ec_set_bit(conf->leds.micmute_led_address, conf->leds.bit); + result = ec_set_bit(conf.leds.micmute_led_address, conf.leds.bit); } else { - result = ec_unset_bit(conf->leds.micmute_led_address, conf->leds.bit); + result = ec_unset_bit(conf.leds.micmute_led_address, conf.leds.bit); } if (result < 0) @@ -1128,9 +1128,9 @@ static int mute_led_sysfs_set(struct led_classdev *led_cdev, int result; if (brightness) { - result = ec_set_bit(conf->leds.mute_led_address, conf->leds.bit); + result = ec_set_bit(conf.leds.mute_led_address, conf.leds.bit); } else { - result = ec_unset_bit(conf->leds.mute_led_address, conf->leds.bit); + result = ec_unset_bit(conf.leds.mute_led_address, conf.leds.bit); } if (result < 0) @@ -1142,7 +1142,7 @@ static int mute_led_sysfs_set(struct led_classdev *led_cdev, static enum led_brightness kbd_bl_sysfs_get(struct led_classdev *led_cdev) { u8 rdata; - int result = ec_read(conf->kbd_bl.bl_state_address, &rdata); + int result = ec_read(conf.kbd_bl.bl_state_address, &rdata); if (result < 0) return 0; return rdata & MSI_EC_KBD_BL_STATE_MASK; @@ -1154,8 +1154,8 @@ static int kbd_bl_sysfs_set(struct led_classdev *led_cdev, u8 wdata; if (brightness < 0 || brightness > 3) return -1; - wdata = conf->kbd_bl.state_base_value | brightness; - return ec_write(conf->kbd_bl.bl_state_address, wdata); + wdata = conf.kbd_bl.state_base_value | brightness; + return ec_write(conf.kbd_bl.bl_state_address, wdata); } static struct led_classdev micmute_led_cdev = { @@ -1201,17 +1201,17 @@ static int __init msi_ec_init(void) } // check if this firmware's configuration is implemented - bool allowed = false; + bool found = false; for (int i = 0; CONFIGURATIONS[i]; i++) { for (int j = 0; CONFIGURATIONS[i]->allowed_fw[j]; j++) { if (strcmp(CONFIGURATIONS[i]->allowed_fw[j], fw_version) == 0) { - allowed = true; - conf = CONFIGURATIONS[i]; + found = true; + memcpy(&conf, CONFIGURATIONS[i], sizeof(struct msi_ec_conf)); break; } } } - if (!allowed) { + if (!found) { pr_err("Your firmware version is not supported!\n"); return -EOPNOTSUPP; } From ded200915f42afd520c019842f3d80dafd73af9e Mon Sep 17 00:00:00 2001 From: teackot Date: Wed, 18 Jan 2023 01:23:25 +0300 Subject: [PATCH 14/28] Don't store FW info addresses in configurations as they are universal --- msi-ec.c | 27 +++++---------------------- registers_configuration.h | 19 ++++++++----------- 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index faca1ca..2493eae 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -100,11 +100,6 @@ static struct msi_ec_conf CONF0 __initdata = { .fan_mode = { .address = 0xf4, }, - .fw = { - .version_address = 0xa0, - .date_address = 0xac, - .time_address = 0xb4, - }, .cpu = { .rt_temp_address = 0x68, .rt_fan_speed_address = 0x71, @@ -182,11 +177,6 @@ static struct msi_ec_conf CONF1 __initdata = { .fan_mode = { .address = 0xd4, }, - .fw = { - .version_address = 0xa0, - .date_address = 0xac, - .time_address = 0xb4, - }, .cpu = { .rt_temp_address = 0x68, .rt_fan_speed_address = 0x71, @@ -265,11 +255,6 @@ static struct msi_ec_conf CONF2 __initdata = { .fan_mode = { .address = 0xd4, }, - .fw = { - .version_address = 0xa0, - .date_address = 0xac, - .time_address = 0xb4, - }, .cpu = { .rt_temp_address = 0x68, .rt_fan_speed_address = 0xc9, @@ -397,7 +382,7 @@ static int ec_check_bit(u8 addr, u8 bit, bool *output) return 0; } -static int ec_get_firmware_version_common_address(u8 buf[MSI_EC_FW_VERSION_LENGTH + 1]) +static int ec_get_firmware_version(u8 buf[MSI_EC_FW_VERSION_LENGTH + 1]) { int result; @@ -820,9 +805,7 @@ static ssize_t fw_version_show(struct device *device, u8 rdata[MSI_EC_FW_VERSION_LENGTH + 1]; int result; - memset(rdata, 0, MSI_EC_FW_VERSION_LENGTH + 1); - result = ec_read_seq(conf.fw.version_address, rdata, - MSI_EC_FW_VERSION_LENGTH); + result = ec_get_firmware_version(rdata); if (result < 0) return result; @@ -838,14 +821,14 @@ static ssize_t fw_release_date_show(struct device *device, int year, month, day, hour, minute, second; memset(rdate, 0, MSI_EC_FW_DATE_LENGTH + 1); - result = ec_read_seq(conf.fw.date_address, rdate, + result = ec_read_seq(MSI_EC_FW_DATE_ADDRESS, rdate, MSI_EC_FW_DATE_LENGTH); if (result < 0) return result; sscanf(rdate, "%02d%02d%04d", &month, &day, &year); memset(rtime, 0, MSI_EC_FW_TIME_LENGTH + 1); - result = ec_read_seq(conf.fw.time_address, rtime, + result = ec_read_seq(MSI_EC_FW_TIME_ADDRESS, rtime, MSI_EC_FW_TIME_LENGTH); if (result < 0) return result; @@ -1195,7 +1178,7 @@ static int __init msi_ec_init(void) // get firmware version u8 fw_version[MSI_EC_FW_VERSION_LENGTH + 1]; - result = ec_get_firmware_version_common_address(fw_version); + result = ec_get_firmware_version(fw_version); if (result < 0) { return result; } diff --git a/registers_configuration.h b/registers_configuration.h index ecfc0dc..0ecaa42 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -5,6 +5,14 @@ #define MSI_DRIVER_NAME "msi-ec" +// Firmware info addresses are universal +#define MSI_EC_FW_VERSION_ADDRESS 0xa0 +#define MSI_EC_FW_DATE_ADDRESS 0xac +#define MSI_EC_FW_TIME_ADDRESS 0xb4 +#define MSI_EC_FW_VERSION_LENGTH 12 +#define MSI_EC_FW_DATE_LENGTH 8 +#define MSI_EC_FW_TIME_LENGTH 8 + struct msi_ec_charge_control_conf { int address; int offset_start; @@ -56,16 +64,6 @@ struct msi_ec_fan_mode_conf { int address; }; -#define MSI_EC_FW_VERSION_ADDRESS 0xa0 -#define MSI_EC_FW_VERSION_LENGTH 12 -#define MSI_EC_FW_DATE_LENGTH 8 -#define MSI_EC_FW_TIME_LENGTH 8 -struct msi_ec_fw_conf { - int version_address; - int date_address; - int time_address; -}; - struct msi_ec_cpu_conf { int rt_temp_address; int rt_fan_speed_address; // realtime @@ -109,7 +107,6 @@ struct msi_ec_conf { struct msi_ec_cooler_boost_conf cooler_boost; struct msi_ec_shift_mode_conf shift_mode; struct msi_ec_fan_mode_conf fan_mode; - struct msi_ec_fw_conf fw; struct msi_ec_cpu_conf cpu; struct msi_ec_gpu_conf gpu; struct msi_ec_led_conf leds; From ca2d620461625efdda7c12d168d4d66adb930ee4 Mon Sep 17 00:00:00 2001 From: teackot Date: Wed, 18 Jan 2023 01:48:34 +0300 Subject: [PATCH 15/28] Use a separate function to load config --- msi-ec.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index 2493eae..2fd8bcd 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -1167,15 +1167,10 @@ static struct led_classdev msiacpi_led_kbdlight = { // Module load/unload // ============================================================ // -static int __init msi_ec_init(void) +static int __init load_configuration(void) { int result; - if (acpi_disabled) { - pr_err("Unable to init because ACPI needs to be enabled first!\n"); - return -ENODEV; - } - // get firmware version u8 fw_version[MSI_EC_FW_VERSION_LENGTH + 1]; result = ec_get_firmware_version(fw_version); @@ -1183,26 +1178,36 @@ static int __init msi_ec_init(void) return result; } - // check if this firmware's configuration is implemented - bool found = false; + // load the suitable configuration, if exists for (int i = 0; CONFIGURATIONS[i]; i++) { for (int j = 0; CONFIGURATIONS[i]->allowed_fw[j]; j++) { if (strcmp(CONFIGURATIONS[i]->allowed_fw[j], fw_version) == 0) { - found = true; memcpy(&conf, CONFIGURATIONS[i], sizeof(struct msi_ec_conf)); - break; + return 0; } } } - if (!found) { - pr_err("Your firmware version is not supported!\n"); - return -EOPNOTSUPP; + + pr_err("Your firmware version is not supported!\n"); + return -EOPNOTSUPP; +} + +static int __init msi_ec_init(void) +{ + int result; + + if (acpi_disabled) { + pr_err("Unable to init because ACPI needs to be enabled first!\n"); + return -ENODEV; } + result = load_configuration(); + if (result < 0) + return result; + result = platform_driver_register(&msi_platform_driver); - if (result < 0) { + if (result < 0) return result; - } msi_platform_device = platform_device_alloc(MSI_DRIVER_NAME, -1); if (msi_platform_device == NULL) { From 8ee8f02b33ed74f4808d77a869abcc05ed72ac0c Mon Sep 17 00:00:00 2001 From: teackot Date: Sat, 4 Feb 2023 03:37:14 +0300 Subject: [PATCH 16/28] Remove unsupported turbo mode from 14C1EMS1.101 configuration --- msi-ec.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 16 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index 2fd8bcd..fd82f0c 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -47,11 +47,9 @@ static const char *const SM_ECO_NAME = "eco"; static const char *const SM_COMFORT_NAME = "comfort"; static const char *const SM_SPORT_NAME = "sport"; static const char *const SM_TURBO_NAME = "turbo"; -static const char *const SM_OVERCLOCK_NAME = "overclock"; static const char *ALLOWED_FW_0[] = { "14C1EMS1.101", - "17F2EMS1.106", NULL, }; @@ -93,9 +91,8 @@ static struct msi_ec_conf CONF0 __initdata = { { SM_ECO_NAME, 0xc2 }, { SM_COMFORT_NAME, 0xc1 }, { SM_SPORT_NAME, 0xc0 }, - { SM_TURBO_NAME, 0xc4 }, }, - .modes_count = 5, + .modes_count = 4, }, .fan_mode = { .address = 0xf4, @@ -129,12 +126,90 @@ static struct msi_ec_conf CONF0 __initdata = { }; static const char *ALLOWED_FW_1[] = { - "1552EMS1.118", + "17F2EMS1.106", NULL, }; static struct msi_ec_conf CONF1 __initdata = { .allowed_fw = ALLOWED_FW_1, + .charge_control = { + .address = 0xef, + .offset_start = 0x8a, + .offset_end = 0x80, + .range_min = 0x8a, + .range_max = 0xe4, + }, + .webcam = { + .address = 0x2e, + .hard_address = 0x2f, + .bit = 1, + }, + .fn_win_swap = { + .address = 0xbf, + .bit = 4, + }, + .battery_mode = { + .address = 0xef, + .modes = { 0xbc, 0xd0, 0xe4 }, + }, + .power_status = { + .address = 0x30, + .lid_open_bit = 1, + .ac_connected_bit = 0, + }, + .cooler_boost = { + .address = 0x98, + .bit = 7, + }, + .shift_mode = { + .address = 0xf2, + .modes = { + { SM_OFF_NAME, 0x80 }, + { SM_ECO_NAME, 0xc2 }, + { SM_COMFORT_NAME, 0xc1 }, + { SM_SPORT_NAME, 0xc0 }, + { SM_TURBO_NAME, 0xc4 }, + }, + .modes_count = 5, + }, + .fan_mode = { + .address = 0xf4, + }, + .cpu = { + .rt_temp_address = 0x68, + .rt_fan_speed_address = 0x71, + .rt_fan_speed_base_min = 0x19, + .rt_fan_speed_base_max = 0x37, + .bs_fan_speed_address = 0x89, + .bs_fan_speed_base_min = 0x00, + .bs_fan_speed_base_max = 0x0f, + }, + .gpu = { + .rt_temp_address = 0x80, + .rt_fan_speed_address = 0x89, + }, + .leds = { + .micmute_led_address = 0x2b, + .mute_led_address = 0x2c, + .bit = 2, + }, + .kbd_bl = { + .bl_mode_address = 0x2c, // ? + .bl_modes = { 0x00, 0x08 }, // ? + .max_mode = 1, // ? + .bl_state_address = 0xf3, + .state_base_value = 0x80, + .max_state = 3, + }, +}; + +static const char *ALLOWED_FW_2[] = { + "1552EMS1.118", + NULL, +}; + +static struct msi_ec_conf CONF2 __initdata = { + .allowed_fw = ALLOWED_FW_2, .charge_control = { .address = 0xd7, .offset_start = 0x8a, @@ -167,10 +242,10 @@ static struct msi_ec_conf CONF1 __initdata = { .shift_mode = { .address = 0xf2, .modes = { - { SM_OFF_NAME, 0x80 }, - { SM_ECO_NAME, 0xc2 }, - { SM_COMFORT_NAME, 0xc1 }, - { SM_OVERCLOCK_NAME, 0xc0 }, + { SM_OFF_NAME, 0x80 }, + { SM_ECO_NAME, 0xc2 }, + { SM_COMFORT_NAME, 0xc1 }, + { SM_SPORT_NAME, 0xc0 }, }, .modes_count = 4, }, @@ -205,14 +280,14 @@ static struct msi_ec_conf CONF1 __initdata = { }, }; -static const char *ALLOWED_FW_2[] = { +static const char *ALLOWED_FW_3[] = { "1592EMS1.111", "E1592IMS.10C", NULL, }; -static struct msi_ec_conf CONF2 __initdata = { - .allowed_fw = ALLOWED_FW_2, +static struct msi_ec_conf CONF3 __initdata = { + .allowed_fw = ALLOWED_FW_3, .charge_control = { .address = 0xef, .offset_start = 0x8a, @@ -245,10 +320,10 @@ static struct msi_ec_conf CONF2 __initdata = { .shift_mode = { .address = 0xd2, .modes = { - { SM_OFF_NAME, 0x80 }, - { SM_ECO_NAME, 0xc2 }, - { SM_COMFORT_NAME, 0xc1 }, - { SM_OVERCLOCK_NAME, 0xc0 }, + { SM_OFF_NAME, 0x80 }, + { SM_ECO_NAME, 0xc2 }, + { SM_COMFORT_NAME, 0xc1 }, + { SM_SPORT_NAME, 0xc0 }, }, .modes_count = 4, }, @@ -287,6 +362,7 @@ static struct msi_ec_conf *CONFIGURATIONS[] __initdata = { &CONF0, &CONF1, &CONF2, + &CONF3, NULL, }; From 1b93b8bbf104b2be779e7ef9b3e2084f02866a10 Mon Sep 17 00:00:00 2001 From: teackot Date: Sun, 5 Feb 2023 22:08:53 +0300 Subject: [PATCH 17/28] Remove off shift mode, 0x80 now means 'unspecified' --- README.md | 13 +++++++------ msi-ec.c | 22 ++++++++++------------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 4afe9d7..4c1ed12 100644 --- a/README.md +++ b/README.md @@ -66,12 +66,13 @@ This driver exports a few files in its own platform device, msi-ec, and is avail - `/sys/devices/platform/msi-ec/shift_mode` - Description: This entry allows switching the shift mode. It provides a set of profiles for gaining CPU & GPU overclock/underclock. - Access: Read, Write - - Valid values: Values reported by `/sys/devices/platform/msi-ec/available_shift_modes`. Some of the possible values: - - off (necessary): operating system decides - - eco: low clock frequency for the CPU & GPU, aka power saving mode - - comfort: dynamic clock frequency for the CPU & GPU, aka power balanced mode - - sport: full clock frequency for the CPU & GPU, aka default desktop mode - - turbo: over-voltage and over-clock for the CPU & GPU, aka overclocking mode + - Valid values: + - unspecified (read-only) + - Values reported by `/sys/devices/platform/msi-ec/available_shift_modes`. Some of the possible values: + - eco: low clock frequency and voltage for the CPU & GPU, aka power saving mode + - comfort: dynamic clock frequency and voltage for the CPU & GPU, aka power balanced mode + - sport: full clock frequency and voltage for the CPU & GPU, aka default desktop mode + - turbo: over-voltage and over-clock for the CPU & GPU, aka overclocking mode - `/sys/devices/platform/msi-ec/available_shift_modes` - Description: This entry reports all supported shift modes. diff --git a/msi-ec.c b/msi-ec.c index fd82f0c..dd343eb 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -42,7 +42,6 @@ #include #include -static const char *const SM_OFF_NAME = "off"; static const char *const SM_ECO_NAME = "eco"; static const char *const SM_COMFORT_NAME = "comfort"; static const char *const SM_SPORT_NAME = "sport"; @@ -87,12 +86,11 @@ static struct msi_ec_conf CONF0 __initdata = { .shift_mode = { .address = 0xf2, .modes = { - { SM_OFF_NAME, 0x80 }, { SM_ECO_NAME, 0xc2 }, { SM_COMFORT_NAME, 0xc1 }, { SM_SPORT_NAME, 0xc0 }, }, - .modes_count = 4, + .modes_count = 3, }, .fan_mode = { .address = 0xf4, @@ -164,13 +162,12 @@ static struct msi_ec_conf CONF1 __initdata = { .shift_mode = { .address = 0xf2, .modes = { - { SM_OFF_NAME, 0x80 }, { SM_ECO_NAME, 0xc2 }, { SM_COMFORT_NAME, 0xc1 }, { SM_SPORT_NAME, 0xc0 }, { SM_TURBO_NAME, 0xc4 }, }, - .modes_count = 5, + .modes_count = 4, }, .fan_mode = { .address = 0xf4, @@ -242,12 +239,11 @@ static struct msi_ec_conf CONF2 __initdata = { .shift_mode = { .address = 0xf2, .modes = { - { SM_OFF_NAME, 0x80 }, { SM_ECO_NAME, 0xc2 }, { SM_COMFORT_NAME, 0xc1 }, { SM_SPORT_NAME, 0xc0 }, }, - .modes_count = 4, + .modes_count = 3, }, .fan_mode = { .address = 0xd4, @@ -320,12 +316,11 @@ static struct msi_ec_conf CONF3 __initdata = { .shift_mode = { .address = 0xd2, .modes = { - { SM_OFF_NAME, 0x80 }, { SM_ECO_NAME, 0xc2 }, { SM_COMFORT_NAME, 0xc1 }, { SM_SPORT_NAME, 0xc0 }, }, - .modes_count = 4, + .modes_count = 3, }, .fan_mode = { .address = 0xd4, @@ -386,7 +381,7 @@ static const struct msi_ec_mode FAN_MODES[] = { #define unset_bit(v, b) (v &= ~(1 << b)) #define check_bit(v, b) ((bool)((v >> b) & 1)) -// compares two, trimming newline at the end the second +// compares two strings, trimming newline at the end the second static int strcmp_trim_newline2(const char *s, const char *s_nl) { size_t s_nl_length = strlen(s_nl); @@ -769,11 +764,11 @@ static ssize_t cooler_boost_store(struct device *dev, if (streq(buf, "on")) result = ec_set_bit(conf.cooler_boost.address, - conf.cooler_boost.bit); + conf.cooler_boost.bit); else if (streq(buf, "off")) result = ec_unset_bit(conf.cooler_boost.address, - conf.cooler_boost.bit); + conf.cooler_boost.bit); if (result < 0) return result; @@ -809,6 +804,9 @@ static ssize_t shift_mode_show(struct device *device, if (result < 0) return result; + if (rdata == 0x80) + return sprintf(buf, "%s\n", "unspecified"); + for (int i = 0; i < conf.shift_mode.modes_count; i++) { if (rdata == conf.shift_mode.modes[i].value) { return sprintf(buf, "%s\n", conf.shift_mode.modes[i].name); From 36de5ab3a589fe5b907143ef8aa36bd57ea32e39 Mon Sep 17 00:00:00 2001 From: teackot Date: Mon, 6 Feb 2023 01:25:10 +0300 Subject: [PATCH 18/28] Added super battery function support --- README.md | 7 +++ msi-ec.c | 103 ++++++++++++++++++++++++++++++++++++++ registers_configuration.h | 7 +++ 3 files changed, 117 insertions(+) diff --git a/README.md b/README.md index 4c1ed12..c4e7da7 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,13 @@ This driver exports a few files in its own platform device, msi-ec, and is avail - Access: Read - Valid values: Newline separated list of strings. +- `/sys/devices/platform/msi-ec/super_battery` + - Description: This entry allows switching the super battery function. + - Access: Read, Write + - Valid values: + - on: super battery function is enabled + - off: super battery function is disabled + - `/sys/devices/platform/msi-ec/fan_mode` - Description: This entry allows switching the fan mode. It provides a set of profiles for adjusting the fan speed under specific criteria. - Access: Read, Write diff --git a/msi-ec.c b/msi-ec.c index dd343eb..65e6681 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -92,6 +92,9 @@ static struct msi_ec_conf CONF0 __initdata = { }, .modes_count = 3, }, + .super_battery = { + .supported = false, + }, .fan_mode = { .address = 0xf4, }, @@ -169,6 +172,9 @@ static struct msi_ec_conf CONF1 __initdata = { }, .modes_count = 4, }, + .super_battery = { + .supported = false, + }, .fan_mode = { .address = 0xf4, }, @@ -245,6 +251,11 @@ static struct msi_ec_conf CONF2 __initdata = { }, .modes_count = 3, }, + .super_battery = { + .supported = true, + .address = 0xeb, + .mask = 0x0f, + }, .fan_mode = { .address = 0xd4, }, @@ -322,6 +333,11 @@ static struct msi_ec_conf CONF3 __initdata = { }, .modes_count = 3, }, + .super_battery = { + .supported = true, + .address = 0xeb, + .mask = 0x0f, + }, .fan_mode = { .address = 0xd4, }, @@ -411,6 +427,48 @@ static int ec_read_seq(u8 addr, u8 *buf, int len) return 0; } +static int ec_set_by_mask(u8 addr, u8 mask) +{ + int result; + u8 stored; + + result = ec_read(addr, &stored); + if (result < 0) + return result; + + stored |= mask; + + return ec_write(addr, stored); +} + +static int ec_unset_by_mask(u8 addr, u8 mask) +{ + int result; + u8 stored; + + result = ec_read(addr, &stored); + if (result < 0) + return result; + + stored &= ~mask; + + return ec_write(addr, stored); +} + +static int ec_check_by_mask(u8 addr, u8 mask, bool *output) +{ + int result; + u8 stored; + + result = ec_read(addr, &stored); + if (result < 0) + return result; + + *output = ((stored & mask) == mask); + + return 0; +} + static int ec_set_bit(u8 addr, u8 bit) { int result; @@ -836,6 +894,49 @@ static ssize_t shift_mode_store(struct device *dev, return -EINVAL; } +static ssize_t super_battery_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + if (!conf.super_battery.supported) + return -EOPNOTSUPP; + + int result; + bool enabled; + + result = ec_check_by_mask(conf.super_battery.address, + conf.super_battery.mask, + &enabled); + + if (enabled) { + return sprintf(buf, "%s\n", "on"); + } else { + return sprintf(buf, "%s\n", "off"); + } +} + +static ssize_t super_battery_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + if (!conf.super_battery.supported) + return -EOPNOTSUPP; + + int result = -EINVAL; + + if (streq(buf, "on")) + result = ec_set_by_mask(conf.super_battery.address, + conf.super_battery.mask); + + else if (streq(buf, "off")) + result = ec_unset_by_mask(conf.super_battery.address, + conf.super_battery.mask); + + if (result < 0) + return result; + + return count; +} + static ssize_t fan_mode_show(struct device *device, struct device_attribute *attr, char *buf) { @@ -921,6 +1022,7 @@ static DEVICE_ATTR_RO(ac_connected); static DEVICE_ATTR_RW(cooler_boost); static DEVICE_ATTR_RO(available_shift_modes); static DEVICE_ATTR_RW(shift_mode); +static DEVICE_ATTR_RW(super_battery); static DEVICE_ATTR_RW(fan_mode); static DEVICE_ATTR_RO(fw_version); static DEVICE_ATTR_RO(fw_release_date); @@ -935,6 +1037,7 @@ static struct attribute *msi_root_attrs[] = { &dev_attr_cooler_boost.attr, &dev_attr_available_shift_modes.attr, &dev_attr_shift_mode.attr, + &dev_attr_super_battery.attr, &dev_attr_fan_mode.attr, &dev_attr_fw_version.attr, &dev_attr_fw_release_date.attr, diff --git a/registers_configuration.h b/registers_configuration.h index 0ecaa42..165bb68 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -60,6 +60,12 @@ struct msi_ec_shift_mode_conf { int modes_count; }; +struct msi_ec_super_battery_conf { + bool supported; + int address; + int mask; +}; + struct msi_ec_fan_mode_conf { int address; }; @@ -106,6 +112,7 @@ struct msi_ec_conf { struct msi_ec_power_status_conf power_status; struct msi_ec_cooler_boost_conf cooler_boost; struct msi_ec_shift_mode_conf shift_mode; + struct msi_ec_super_battery_conf super_battery; struct msi_ec_fan_mode_conf fan_mode; struct msi_ec_cpu_conf cpu; struct msi_ec_gpu_conf gpu; From 414629a50a4badf79fb781aca3b555b1357f5f8e Mon Sep 17 00:00:00 2001 From: teackot Date: Mon, 6 Feb 2023 21:21:50 +0300 Subject: [PATCH 19/28] Move allowed firmware arrays to init section --- msi-ec.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index 65e6681..52783a0 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -47,7 +47,7 @@ static const char *const SM_COMFORT_NAME = "comfort"; static const char *const SM_SPORT_NAME = "sport"; static const char *const SM_TURBO_NAME = "turbo"; -static const char *ALLOWED_FW_0[] = { +static const char *ALLOWED_FW_0[] __initdata = { "14C1EMS1.101", NULL, }; @@ -126,7 +126,7 @@ static struct msi_ec_conf CONF0 __initdata = { }, }; -static const char *ALLOWED_FW_1[] = { +static const char *ALLOWED_FW_1[] __initdata = { "17F2EMS1.106", NULL, }; @@ -206,7 +206,7 @@ static struct msi_ec_conf CONF1 __initdata = { }, }; -static const char *ALLOWED_FW_2[] = { +static const char *ALLOWED_FW_2[] __initdata = { "1552EMS1.118", NULL, }; @@ -287,7 +287,7 @@ static struct msi_ec_conf CONF2 __initdata = { }, }; -static const char *ALLOWED_FW_3[] = { +static const char *ALLOWED_FW_3[] __initdata = { "1592EMS1.111", "E1592IMS.10C", NULL, @@ -1360,6 +1360,7 @@ static int __init load_configuration(void) for (int j = 0; CONFIGURATIONS[i]->allowed_fw[j]; j++) { if (strcmp(CONFIGURATIONS[i]->allowed_fw[j], fw_version) == 0) { memcpy(&conf, CONFIGURATIONS[i], sizeof(struct msi_ec_conf)); + conf.allowed_fw = NULL; return 0; } } From 2d40b8f622b226b30122fcb1c614435021a5bfbe Mon Sep 17 00:00:00 2001 From: teackot Date: Tue, 7 Feb 2023 03:11:57 +0300 Subject: [PATCH 20/28] Implement webcam blocking --- README.md | 9 +++- msi-ec.c | 111 ++++++++++++++++++++++++++------------ registers_configuration.h | 2 +- 3 files changed, 87 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index c4e7da7..92148a5 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,19 @@ Also, and until future enhancements, no DMI data is used to identify your laptop This driver exports a few files in its own platform device, msi-ec, and is available to userspace under: - `/sys/devices/platform/msi-ec/webcam` - - Description: This entry allows enabling the integrated webcam. + - Description: This entry allows enabling the integrated webcam (as if it was done by a keyboard button). - Access: Read, Write - Valid values: - on: integrated webcam is enabled - off: integrated webcam is disabled +- `/sys/devices/platform/msi-ec/webcam_block` + - Description: This entry allows blocking the integrated webcam. Being blocked by this entry, webcam can't be enabled by a keyboard button or by writing into the webcam file. + - Access: Read, Write + - Valid values: + - on: integrated webcam is blocked + - off: integrated webcam is not blocked + - `/sys/devices/platform/msi-ec/fn_key` - Description: This entry allows switching the position between the function key and the windows key. - Access: Read, Write diff --git a/msi-ec.c b/msi-ec.c index 52783a0..ed4b53a 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -62,9 +62,9 @@ static struct msi_ec_conf CONF0 __initdata = { .range_max = 0xe4, }, .webcam = { - .address = 0x2e, - .hard_address = 0x2f, - .bit = 1, + .address = 0x2e, + .block_address = 0x2f, + .bit = 1, }, .fn_win_swap = { .address = 0xbf, @@ -142,7 +142,7 @@ static struct msi_ec_conf CONF1 __initdata = { }, .webcam = { .address = 0x2e, - .hard_address = 0x2f, + .block_address = 0x2f, .bit = 1, }, .fn_win_swap = { @@ -222,7 +222,7 @@ static struct msi_ec_conf CONF2 __initdata = { }, .webcam = { .address = 0x2e, - .hard_address = 0x2f, + .block_address = 0x2f, .bit = 1, }, .fn_win_swap = { @@ -304,7 +304,7 @@ static struct msi_ec_conf CONF3 __initdata = { }, .webcam = { .address = 0x2e, - .hard_address = 0x2f, + .block_address = 0x2f, .bit = 1, }, .fn_win_swap = { @@ -542,22 +542,6 @@ static ssize_t charge_control_threshold_show(u8 offset, struct device *device, return sprintf(buf, "%i\n", rdata - offset); } -static ssize_t -charge_control_start_threshold_show(struct device *device, - struct device_attribute *attr, char *buf) -{ - return charge_control_threshold_show(conf.charge_control.offset_start, - device, attr, buf); -} - -static ssize_t charge_control_end_threshold_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - return charge_control_threshold_show(conf.charge_control.offset_end, - device, attr, buf); -} - static ssize_t charge_control_threshold_store(u8 offset, struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -581,6 +565,14 @@ static ssize_t charge_control_threshold_store(u8 offset, struct device *dev, return count; } +static ssize_t +charge_control_start_threshold_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + return charge_control_threshold_show(conf.charge_control.offset_start, + device, attr, buf); +} + static ssize_t charge_control_start_threshold_store(struct device *dev, struct device_attribute *attr, @@ -590,6 +582,14 @@ charge_control_start_threshold_store(struct device *dev, conf.charge_control.offset_start, dev, attr, buf, count); } +static ssize_t charge_control_end_threshold_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + return charge_control_threshold_show(conf.charge_control.offset_end, + device, attr, buf); +} + static ssize_t charge_control_end_threshold_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -632,31 +632,38 @@ static struct acpi_battery_hook battery_hook = { // Sysfs platform device attributes (root) // ============================================================ // -static ssize_t webcam_show(struct device *device, struct device_attribute *attr, - char *buf) +static ssize_t webcam_common_show(u8 address, + char *buf, + const char *str_on_0, + const char *str_on_1) { int result; bool bit_value; - result = ec_check_bit(conf.webcam.address, conf.webcam.bit, &bit_value); + result = ec_check_bit(address, conf.webcam.bit, &bit_value); + if (result < 0) + return result; if (bit_value) { - return sprintf(buf, "%s\n", "on"); + return sprintf(buf, "%s\n", str_on_1); } else { - return sprintf(buf, "%s\n", "off"); + return sprintf(buf, "%s\n", str_on_0); } } -static ssize_t webcam_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t webcam_common_store(u8 address, + const char *buf, + size_t count, + const char *str_for_0, + const char *str_for_1) { int result = -EINVAL; - if (streq(buf, "on")) - result = ec_set_bit(conf.webcam.address, conf.webcam.bit); + if (strcmp_trim_newline2(str_for_1, buf) == 0) + result = ec_set_bit(address, conf.webcam.bit); - if (streq(buf, "off")) - result = ec_unset_bit(conf.webcam.address, conf.webcam.bit); + if (strcmp_trim_newline2(str_for_0, buf) == 0) + result = ec_unset_bit(address, conf.webcam.bit); if (result < 0) return result; @@ -664,6 +671,42 @@ static ssize_t webcam_store(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t webcam_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + return webcam_common_show(conf.webcam.address, + buf, + "off", "on"); +} + +static ssize_t webcam_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return webcam_common_store(conf.webcam.address, + buf, count, + "off", "on"); +} + +static ssize_t webcam_block_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + return webcam_common_show(conf.webcam.block_address, + buf, + "on", "off"); +} + +static ssize_t webcam_block_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return webcam_common_store(conf.webcam.block_address, + buf, count, + "on", "off"); +} + static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, char *buf) { @@ -1014,6 +1057,7 @@ static ssize_t fw_release_date_show(struct device *device, } static DEVICE_ATTR_RW(webcam); +static DEVICE_ATTR_RW(webcam_block); static DEVICE_ATTR_RW(fn_key); static DEVICE_ATTR_RW(win_key); static DEVICE_ATTR_RW(battery_mode); @@ -1029,6 +1073,7 @@ static DEVICE_ATTR_RO(fw_release_date); static struct attribute *msi_root_attrs[] = { &dev_attr_webcam.attr, + &dev_attr_webcam_block.attr, &dev_attr_fn_key.attr, &dev_attr_win_key.attr, &dev_attr_battery_mode.attr, diff --git a/registers_configuration.h b/registers_configuration.h index 165bb68..8f4d000 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -23,7 +23,7 @@ struct msi_ec_charge_control_conf { struct msi_ec_webcam_conf { int address; - int hard_address; + int block_address; int bit; }; From f8fa23e6f7d159e407a7ab6167985db25162b636 Mon Sep 17 00:00:00 2001 From: teackot Date: Tue, 7 Feb 2023 19:00:50 +0300 Subject: [PATCH 21/28] Remove unnecesary battery_mode configuration entry --- msi-ec.c | 40 ++++++++++++--------------------------- registers_configuration.h | 6 ------ 2 files changed, 12 insertions(+), 34 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index ed4b53a..935ba70 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -70,10 +70,6 @@ static struct msi_ec_conf CONF0 __initdata = { .address = 0xbf, .bit = 4, }, - .battery_mode = { - .address = 0xef, - .modes = { 0xbc, 0xd0, 0xe4 }, - }, .power_status = { .address = 0x30, .lid_open_bit = 1, @@ -149,10 +145,6 @@ static struct msi_ec_conf CONF1 __initdata = { .address = 0xbf, .bit = 4, }, - .battery_mode = { - .address = 0xef, - .modes = { 0xbc, 0xd0, 0xe4 }, - }, .power_status = { .address = 0x30, .lid_open_bit = 1, @@ -229,10 +221,6 @@ static struct msi_ec_conf CONF2 __initdata = { .address = 0xe8, .bit = 4, }, - .battery_mode = { - .address = 0xd7, - .modes = { 0xbc, 0xd0, 0xe4 }, - }, .power_status = { .address = 0x30, .lid_open_bit = 1, @@ -311,10 +299,6 @@ static struct msi_ec_conf CONF3 __initdata = { .address = 0xe8, .bit = 4, }, - .battery_mode = { - .address = 0xef, - .modes = { 0xbc, 0xd0, 0xe4 }, - }, .power_status = { .address = 0x30, .lid_open_bit = 1, @@ -777,15 +761,15 @@ static ssize_t battery_mode_show(struct device *device, u8 rdata; int result; - result = ec_read(conf.battery_mode.address, &rdata); + result = ec_read(conf.charge_control.address, &rdata); if (result < 0) return result; - if (rdata == conf.battery_mode.modes[2]) { + if (rdata == conf.charge_control.range_max) { return sprintf(buf, "%s\n", "max"); - } else if (rdata == conf.battery_mode.modes[1]) { + } else if (rdata == conf.charge_control.offset_end + 80) { // up to 80% return sprintf(buf, "%s\n", "medium"); - } else if (rdata == conf.battery_mode.modes[0]) { + } else if (rdata == conf.charge_control.offset_end + 60) { // up to 60% return sprintf(buf, "%s\n", "min"); } else { return sprintf(buf, "%s (%i)\n", "unknown", rdata); @@ -799,16 +783,16 @@ static ssize_t battery_mode_store(struct device *dev, int result = -EINVAL; if (streq(buf, "max")) - result = ec_write(conf.battery_mode.address, - conf.battery_mode.modes[2]); + result = ec_write(conf.charge_control.address, + conf.charge_control.range_max); - else if (streq(buf, "medium")) - result = ec_write(conf.battery_mode.address, - conf.battery_mode.modes[1]); + else if (streq(buf, "medium")) // up to 80% + result = ec_write(conf.charge_control.address, + conf.charge_control.offset_end + 80); - else if (streq(buf, "min")) - result = ec_write(conf.battery_mode.address, - conf.battery_mode.modes[0]); + else if (streq(buf, "min")) // up to 60% + result = ec_write(conf.charge_control.address, + conf.charge_control.offset_end + 60); if (result < 0) return result; diff --git a/registers_configuration.h b/registers_configuration.h index 8f4d000..2b087ec 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -32,11 +32,6 @@ struct msi_ec_fn_win_swap_conf { int bit; }; -struct msi_ec_battery_mode_conf { - int address; - int modes[3]; // min, mid, max -}; - struct msi_ec_power_status_conf { int address; int lid_open_bit; @@ -108,7 +103,6 @@ struct msi_ec_conf { struct msi_ec_charge_control_conf charge_control; struct msi_ec_webcam_conf webcam; struct msi_ec_fn_win_swap_conf fn_win_swap; - struct msi_ec_battery_mode_conf battery_mode; struct msi_ec_power_status_conf power_status; struct msi_ec_cooler_boost_conf cooler_boost; struct msi_ec_shift_mode_conf shift_mode; From e0ee5e417f65ce6e80e9ff333775b1b64692ff78 Mon Sep 17 00:00:00 2001 From: teackot Date: Sat, 11 Feb 2023 09:38:22 +0300 Subject: [PATCH 22/28] Add GS66 11UE (16V4EMS1.114) configuration (#9) --- msi-ec.c | 96 +++++++++++++++++++++++++++++++++++---- registers_configuration.h | 10 ++-- 2 files changed, 93 insertions(+), 13 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index 935ba70..b75c62b 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -137,9 +137,9 @@ static struct msi_ec_conf CONF1 __initdata = { .range_max = 0xe4, }, .webcam = { - .address = 0x2e, + .address = 0x2e, .block_address = 0x2f, - .bit = 1, + .bit = 1, }, .fn_win_swap = { .address = 0xbf, @@ -213,9 +213,9 @@ static struct msi_ec_conf CONF2 __initdata = { .range_max = 0xe4, }, .webcam = { - .address = 0x2e, + .address = 0x2e, .block_address = 0x2f, - .bit = 1, + .bit = 1, }, .fn_win_swap = { .address = 0xe8, @@ -291,9 +291,9 @@ static struct msi_ec_conf CONF3 __initdata = { .range_max = 0xe4, }, .webcam = { - .address = 0x2e, + .address = 0x2e, .block_address = 0x2f, - .bit = 1, + .bit = 1, }, .fn_win_swap = { .address = 0xe8, @@ -353,11 +353,89 @@ static struct msi_ec_conf CONF3 __initdata = { }, }; +static const char *ALLOWED_FW_4[] __initdata = { + "16V4EMS1.114", + NULL, +}; + +static struct msi_ec_conf CONF4 __initdata = { + .allowed_fw = ALLOWED_FW_4, + .charge_control = { + .address = 0xd7, + .offset_start = 0x8a, + .offset_end = 0x80, + .range_min = 0x8a, + .range_max = 0xe4, + }, + .webcam = { + .address = 0x2e, + .block_address = 0x2f, + .bit = 1, + }, + .fn_win_swap = { + .address = MSI_EC_ADDR_UNKNOWN, // supported, but unknown + .bit = 4, + }, + .power_status = { + .address = 0x30, + .lid_open_bit = 1, + .ac_connected_bit = 0, + }, + .cooler_boost = { + .address = 0x98, + .bit = 7, + }, + .shift_mode = { + .address = 0xd2, + .modes = { + { SM_ECO_NAME, 0xc2 }, + { SM_COMFORT_NAME, 0xc1 }, + { SM_SPORT_NAME, 0xc0 }, + }, + .modes_count = 3, + }, + .super_battery = { + .supported = false, // supported, but address is unknown + .address = MSI_EC_ADDR_UNKNOWN, + .mask = 0x0f, + }, + .fan_mode = { + .address = 0xd4, + }, + .cpu = { + .rt_temp_address = 0x68, + .rt_fan_speed_address = MSI_EC_ADDR_UNKNOWN, + .rt_fan_speed_base_min = 0x19, + .rt_fan_speed_base_max = 0x37, + .bs_fan_speed_address = 0x89, + .bs_fan_speed_base_min = 0x00, + .bs_fan_speed_base_max = 0x0f, + }, + .gpu = { + .rt_temp_address = 0x80, + .rt_fan_speed_address = 0x89, + }, + .leds = { + .micmute_led_address = MSI_EC_ADDR_UNKNOWN, + .mute_led_address = MSI_EC_ADDR_UNKNOWN, + .bit = 1, + }, + .kbd_bl = { + .bl_mode_address = MSI_EC_ADDR_UNKNOWN, // ? + .bl_modes = { 0x00, 0x08 }, // ? + .max_mode = 1, // ? + .bl_state_address = 0xd3, + .state_base_value = 0x80, + .max_state = 3, + }, +}; + static struct msi_ec_conf *CONFIGURATIONS[] __initdata = { &CONF0, &CONF1, &CONF2, &CONF3, + &CONF4, NULL, }; @@ -609,7 +687,7 @@ static int msi_battery_remove(struct power_supply *battery) static struct acpi_battery_hook battery_hook = { .add_battery = msi_battery_add, .remove_battery = msi_battery_remove, - .name = MSI_DRIVER_NAME, + .name = MSI_EC_DRIVER_NAME, }; // ============================================================ // @@ -1284,7 +1362,7 @@ static struct platform_device *msi_platform_device; static struct platform_driver msi_platform_driver = { .driver = { - .name = MSI_DRIVER_NAME, + .name = MSI_EC_DRIVER_NAME, }, .probe = msi_platform_probe, .remove = msi_platform_remove, @@ -1416,7 +1494,7 @@ static int __init msi_ec_init(void) if (result < 0) return result; - msi_platform_device = platform_device_alloc(MSI_DRIVER_NAME, -1); + msi_platform_device = platform_device_alloc(MSI_EC_DRIVER_NAME, -1); if (msi_platform_device == NULL) { platform_driver_unregister(&msi_platform_driver); return -ENOMEM; diff --git a/registers_configuration.h b/registers_configuration.h index 2b087ec..2676670 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -1,9 +1,11 @@ -#ifndef __MSI_EC_CONSTANTS__ -#define __MSI_EC_CONSTANTS__ +#ifndef __MSI_EC_REGISTERS_CONFIG__ +#define __MSI_EC_REGISTERS_CONFIG__ #include -#define MSI_DRIVER_NAME "msi-ec" +#define MSI_EC_DRIVER_NAME "msi-ec" + +#define MSI_EC_ADDR_UNKNOWN 0xff00 // unknown address // Firmware info addresses are universal #define MSI_EC_FW_VERSION_ADDRESS 0xa0 @@ -114,4 +116,4 @@ struct msi_ec_conf { struct msi_ec_kbd_bl_conf kbd_bl; }; -#endif // __MSI_EC_CONSTANTS__ +#endif // __MSI_EC_REGISTERS_CONFIG__ From 185d230bf10b7530baf2823e2e77f591fc5ac93a Mon Sep 17 00:00:00 2001 From: teackot Date: Sat, 11 Feb 2023 10:26:53 +0300 Subject: [PATCH 23/28] Return an error if attribute is not supported (temporary until I implement not creating such attributes) --- msi-ec.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index b75c62b..f405055 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -699,6 +699,9 @@ static ssize_t webcam_common_show(u8 address, const char *str_on_0, const char *str_on_1) { + if (address == MSI_EC_ADDR_UNKNOWN) + return -EOPNOTSUPP; + int result; bool bit_value; @@ -719,6 +722,9 @@ static ssize_t webcam_common_store(u8 address, const char *str_for_0, const char *str_for_1) { + if (address == MSI_EC_ADDR_UNKNOWN) + return -EOPNOTSUPP; + int result = -EINVAL; if (strcmp_trim_newline2(str_for_1, buf) == 0) @@ -772,6 +778,9 @@ static ssize_t webcam_block_store(struct device *dev, static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, char *buf) { + if (conf.fn_win_swap.address == MSI_EC_ADDR_UNKNOWN) + return -EOPNOTSUPP; + int result; bool bit_value; @@ -787,6 +796,9 @@ static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, static ssize_t fn_key_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + if (conf.fn_win_swap.address == MSI_EC_ADDR_UNKNOWN) + return -EOPNOTSUPP; + int result; if (streq(buf, "right")) { @@ -804,6 +816,9 @@ static ssize_t fn_key_store(struct device *dev, struct device_attribute *attr, static ssize_t win_key_show(struct device *device, struct device_attribute *attr, char *buf) { + if (conf.fn_win_swap.address == MSI_EC_ADDR_UNKNOWN) + return -EOPNOTSUPP; + int result; bool bit_value; @@ -819,6 +834,9 @@ static ssize_t win_key_show(struct device *device, static ssize_t win_key_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + if (conf.fn_win_swap.address == MSI_EC_ADDR_UNKNOWN) + return -EOPNOTSUPP; + int result; if (streq(buf, "right")) { @@ -907,6 +925,9 @@ static ssize_t ac_connected_show(struct device *device, static ssize_t cooler_boost_show(struct device *device, struct device_attribute *attr, char *buf) { + if (conf.cooler_boost.address == MSI_EC_ADDR_UNKNOWN) + return -EOPNOTSUPP; + int result; bool bit_value; @@ -923,6 +944,9 @@ static ssize_t cooler_boost_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + if (conf.cooler_boost.address == MSI_EC_ADDR_UNKNOWN) + return -EOPNOTSUPP; + int result = -EINVAL; if (streq(buf, "on")) @@ -1002,7 +1026,7 @@ static ssize_t shift_mode_store(struct device *dev, static ssize_t super_battery_show(struct device *device, struct device_attribute *attr, char *buf) { - if (!conf.super_battery.supported) + if (conf.super_battery.address == MSI_EC_ADDR_UNKNOWN) return -EOPNOTSUPP; int result; @@ -1023,6 +1047,9 @@ static ssize_t super_battery_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + if (conf.super_battery.address == MSI_EC_ADDR_UNKNOWN) + return -EOPNOTSUPP; + if (!conf.super_battery.supported) return -EOPNOTSUPP; @@ -1045,6 +1072,9 @@ static ssize_t super_battery_store(struct device *dev, static ssize_t fan_mode_show(struct device *device, struct device_attribute *attr, char *buf) { + if (conf.fan_mode.address == MSI_EC_ADDR_UNKNOWN) + return -EOPNOTSUPP; + u8 rdata; int result; @@ -1064,6 +1094,9 @@ static ssize_t fan_mode_show(struct device *device, static ssize_t fan_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + if (conf.fan_mode.address == MSI_EC_ADDR_UNKNOWN) + return -EOPNOTSUPP; + int result; for (int i = 0; i < FAN_MODES_COUNT; i++) { @@ -1509,9 +1542,15 @@ static int __init msi_ec_init(void) battery_hook_register(&battery_hook); - led_classdev_register(&msi_platform_device->dev, &micmute_led_cdev); - led_classdev_register(&msi_platform_device->dev, &mute_led_cdev); - led_classdev_register(&msi_platform_device->dev, &msiacpi_led_kbdlight); + // register LED classdevs + if (conf.leds.micmute_led_address != MSI_EC_ADDR_UNKNOWN) + led_classdev_register(&msi_platform_device->dev, &micmute_led_cdev); + + if (conf.leds.mute_led_address != MSI_EC_ADDR_UNKNOWN) + led_classdev_register(&msi_platform_device->dev, &mute_led_cdev); + + if (conf.kbd_bl.bl_state_address != MSI_EC_ADDR_UNKNOWN) + led_classdev_register(&msi_platform_device->dev, &msiacpi_led_kbdlight); pr_info("msi-ec: module_init\n"); return 0; @@ -1519,9 +1558,15 @@ static int __init msi_ec_init(void) static void __exit msi_ec_exit(void) { - led_classdev_unregister(&mute_led_cdev); - led_classdev_unregister(&micmute_led_cdev); - led_classdev_unregister(&msiacpi_led_kbdlight); + // unregister LED classdevs + if (conf.leds.micmute_led_address != MSI_EC_ADDR_UNKNOWN) + led_classdev_unregister(&micmute_led_cdev); + + if (conf.leds.mute_led_address != MSI_EC_ADDR_UNKNOWN) + led_classdev_unregister(&mute_led_cdev); + + if (conf.kbd_bl.bl_state_address != MSI_EC_ADDR_UNKNOWN) + led_classdev_unregister(&msiacpi_led_kbdlight); battery_hook_unregister(&battery_hook); From 845fe78e6dee1dd9e81efe8e769e500e96fbde3d Mon Sep 17 00:00:00 2001 From: teackot Date: Sat, 11 Feb 2023 12:23:18 +0300 Subject: [PATCH 24/28] Only create supported attributes --- msi-ec.c | 157 ++++++++++++++++++++++---------------- registers_configuration.h | 1 - 2 files changed, 90 insertions(+), 68 deletions(-) diff --git a/msi-ec.c b/msi-ec.c index f405055..4a09aad 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -89,7 +89,7 @@ static struct msi_ec_conf CONF0 __initdata = { .modes_count = 3, }, .super_battery = { - .supported = false, + .address = MSI_EC_ADDR_UNKNOWN, }, .fan_mode = { .address = 0xf4, @@ -165,7 +165,7 @@ static struct msi_ec_conf CONF1 __initdata = { .modes_count = 4, }, .super_battery = { - .supported = false, + .address = MSI_EC_ADDR_UNKNOWN, }, .fan_mode = { .address = 0xf4, @@ -240,7 +240,6 @@ static struct msi_ec_conf CONF2 __initdata = { .modes_count = 3, }, .super_battery = { - .supported = true, .address = 0xeb, .mask = 0x0f, }, @@ -318,7 +317,6 @@ static struct msi_ec_conf CONF3 __initdata = { .modes_count = 3, }, .super_battery = { - .supported = true, .address = 0xeb, .mask = 0x0f, }, @@ -394,8 +392,7 @@ static struct msi_ec_conf CONF4 __initdata = { }, .modes_count = 3, }, - .super_battery = { - .supported = false, // supported, but address is unknown + .super_battery = { // supported, but address is unknown .address = MSI_EC_ADDR_UNKNOWN, .mask = 0x0f, }, @@ -453,6 +450,11 @@ static const struct msi_ec_mode FAN_MODES[] = { { FM_ADVANCED_NAME, 0x8d } }; +struct attribute_support { + struct attribute *attribute; + bool supported; +}; + #define streq(x, y) (strcmp(x, y) == 0 || strcmp(x, y "\n") == 0) #define set_bit(v, b) (v |= (1 << b)) @@ -699,9 +701,6 @@ static ssize_t webcam_common_show(u8 address, const char *str_on_0, const char *str_on_1) { - if (address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - int result; bool bit_value; @@ -722,9 +721,6 @@ static ssize_t webcam_common_store(u8 address, const char *str_for_0, const char *str_for_1) { - if (address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - int result = -EINVAL; if (strcmp_trim_newline2(str_for_1, buf) == 0) @@ -778,9 +774,6 @@ static ssize_t webcam_block_store(struct device *dev, static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, char *buf) { - if (conf.fn_win_swap.address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - int result; bool bit_value; @@ -796,9 +789,6 @@ static ssize_t fn_key_show(struct device *device, struct device_attribute *attr, static ssize_t fn_key_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - if (conf.fn_win_swap.address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - int result; if (streq(buf, "right")) { @@ -816,9 +806,6 @@ static ssize_t fn_key_store(struct device *dev, struct device_attribute *attr, static ssize_t win_key_show(struct device *device, struct device_attribute *attr, char *buf) { - if (conf.fn_win_swap.address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - int result; bool bit_value; @@ -834,9 +821,6 @@ static ssize_t win_key_show(struct device *device, static ssize_t win_key_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - if (conf.fn_win_swap.address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - int result; if (streq(buf, "right")) { @@ -925,9 +909,6 @@ static ssize_t ac_connected_show(struct device *device, static ssize_t cooler_boost_show(struct device *device, struct device_attribute *attr, char *buf) { - if (conf.cooler_boost.address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - int result; bool bit_value; @@ -944,9 +925,6 @@ static ssize_t cooler_boost_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - if (conf.cooler_boost.address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - int result = -EINVAL; if (streq(buf, "on")) @@ -1026,9 +1004,6 @@ static ssize_t shift_mode_store(struct device *dev, static ssize_t super_battery_show(struct device *device, struct device_attribute *attr, char *buf) { - if (conf.super_battery.address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - int result; bool enabled; @@ -1047,12 +1022,6 @@ static ssize_t super_battery_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - if (conf.super_battery.address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - - if (!conf.super_battery.supported) - return -EOPNOTSUPP; - int result = -EINVAL; if (streq(buf, "on")) @@ -1072,9 +1041,6 @@ static ssize_t super_battery_store(struct device *dev, static ssize_t fan_mode_show(struct device *device, struct device_attribute *attr, char *buf) { - if (conf.fan_mode.address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - u8 rdata; int result; @@ -1094,9 +1060,6 @@ static ssize_t fan_mode_show(struct device *device, static ssize_t fan_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - if (conf.fan_mode.address == MSI_EC_ADDR_UNKNOWN) - return -EOPNOTSUPP; - int result; for (int i = 0; i < FAN_MODES_COUNT; i++) { @@ -1166,28 +1129,6 @@ static DEVICE_ATTR_RW(fan_mode); static DEVICE_ATTR_RO(fw_version); static DEVICE_ATTR_RO(fw_release_date); -static struct attribute *msi_root_attrs[] = { - &dev_attr_webcam.attr, - &dev_attr_webcam_block.attr, - &dev_attr_fn_key.attr, - &dev_attr_win_key.attr, - &dev_attr_battery_mode.attr, - &dev_attr_lid_status.attr, - &dev_attr_ac_connected.attr, - &dev_attr_cooler_boost.attr, - &dev_attr_available_shift_modes.attr, - &dev_attr_shift_mode.attr, - &dev_attr_super_battery.attr, - &dev_attr_fan_mode.attr, - &dev_attr_fw_version.attr, - &dev_attr_fw_release_date.attr, - NULL, -}; - -static const struct attribute_group msi_root_group = { - .attrs = msi_root_attrs, -}; - // ============================================================ // // Sysfs platform device attributes (cpu) // ============================================================ // @@ -1369,6 +1310,8 @@ static const struct attribute_group msi_gpu_group = { .attrs = msi_gpu_attrs, }; +static struct attribute_group msi_root_group; + static const struct attribute_group *msi_platform_groups[] = { &msi_root_group, &msi_cpu_group, @@ -1379,15 +1322,94 @@ static const struct attribute_group *msi_platform_groups[] = { static int msi_platform_probe(struct platform_device *pdev) { int result; + + // ALL root attributes and their support flags + struct attribute_support msi_root_attrs_support[] = { + { + &dev_attr_webcam.attr, + conf.webcam.address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_webcam_block.attr, + conf.webcam.block_address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_fn_key.attr, + conf.fn_win_swap.address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_win_key.attr, + conf.fn_win_swap.address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_battery_mode.attr, + conf.charge_control.address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_lid_status.attr, + conf.power_status.address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_ac_connected.attr, + conf.power_status.address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_cooler_boost.attr, + conf.cooler_boost.address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_available_shift_modes.attr, + conf.shift_mode.address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_shift_mode.attr, + conf.shift_mode.address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_super_battery.attr, + conf.super_battery.address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_fan_mode.attr, + conf.fan_mode.address != MSI_EC_ADDR_UNKNOWN, + }, + { + &dev_attr_fw_version.attr, + true, + }, + { + &dev_attr_fw_release_date.attr, + true, + }, + }; + + const int attributes_count = + sizeof(msi_root_attrs_support) / sizeof(msi_root_attrs_support[0]); + + // supported root attributes + struct attribute **msi_root_attrs = + kcalloc(attributes_count, sizeof(struct attribute *), GFP_KERNEL); + + // copy supported attributes only + for (int i = 0, j = 0; i < attributes_count; i++) { + if (msi_root_attrs_support[i].supported) + msi_root_attrs[j++] = msi_root_attrs_support[i].attribute; + } + + // save attributes in the group + msi_root_group.attrs = msi_root_attrs; + result = sysfs_create_groups(&pdev->dev.kobj, msi_platform_groups); if (result < 0) return result; + return 0; } static int msi_platform_remove(struct platform_device *pdev) { sysfs_remove_groups(&pdev->dev.kobj, msi_platform_groups); + kvfree(msi_root_group.attrs); return 0; } @@ -1484,6 +1506,7 @@ static struct led_classdev msiacpi_led_kbdlight = { // Module load/unload // ============================================================ // +// must be called before msi_platform_probe() static int __init load_configuration(void) { int result; diff --git a/registers_configuration.h b/registers_configuration.h index 2676670..42fa748 100644 --- a/registers_configuration.h +++ b/registers_configuration.h @@ -58,7 +58,6 @@ struct msi_ec_shift_mode_conf { }; struct msi_ec_super_battery_conf { - bool supported; int address; int mask; }; From 2d14c1e167fa32903904c11be5d3babff8067f68 Mon Sep 17 00:00:00 2001 From: teackot Date: Thu, 16 Feb 2023 11:32:06 +0300 Subject: [PATCH 25/28] Simplify searching for a suitable conf by using match_string; I also renamed the header file to be more descriptive --- ...nfiguration.h => ec_memory_configuration.h | 0 msi-ec.c | 21 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) rename registers_configuration.h => ec_memory_configuration.h (100%) diff --git a/registers_configuration.h b/ec_memory_configuration.h similarity index 100% rename from registers_configuration.h rename to ec_memory_configuration.h diff --git a/msi-ec.c b/msi-ec.c index 4a09aad..14b0964 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -31,7 +31,7 @@ * */ -#include "registers_configuration.h" +#include "ec_memory_configuration.h" #include #include @@ -41,6 +41,7 @@ #include #include #include +#include static const char *const SM_ECO_NAME = "eco"; static const char *const SM_COMFORT_NAME = "comfort"; @@ -1512,20 +1513,20 @@ static int __init load_configuration(void) int result; // get firmware version - u8 fw_version[MSI_EC_FW_VERSION_LENGTH + 1]; - result = ec_get_firmware_version(fw_version); + u8 ver[MSI_EC_FW_VERSION_LENGTH + 1]; + result = ec_get_firmware_version(ver); if (result < 0) { return result; } // load the suitable configuration, if exists for (int i = 0; CONFIGURATIONS[i]; i++) { - for (int j = 0; CONFIGURATIONS[i]->allowed_fw[j]; j++) { - if (strcmp(CONFIGURATIONS[i]->allowed_fw[j], fw_version) == 0) { - memcpy(&conf, CONFIGURATIONS[i], sizeof(struct msi_ec_conf)); - conf.allowed_fw = NULL; - return 0; - } + if (match_string(CONFIGURATIONS[i]->allowed_fw, -1, ver) != -EINVAL) { + memcpy(&conf, + CONFIGURATIONS[i], + sizeof(struct msi_ec_conf)); + conf.allowed_fw = NULL; + return 0; } } @@ -1602,7 +1603,7 @@ static void __exit msi_ec_exit(void) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jose Angel Pastrana "); MODULE_AUTHOR("Aakash Singh "); -MODULE_AUTHOR("Nikita Kravets "); +MODULE_AUTHOR("Nikita Kravets "); MODULE_DESCRIPTION("MSI Embedded Controller"); MODULE_VERSION("0.08"); From cb0fd5c11a2d39bc1f5b69d400ae0ae967e0589f Mon Sep 17 00:00:00 2001 From: teackot Date: Thu, 16 Feb 2023 12:11:35 +0300 Subject: [PATCH 26/28] Allow to specify available fan modes in configs --- README.md | 23 +++++++---- ec_memory_configuration.h | 2 + msi-ec.c | 86 +++++++++++++++++++++++++++++++-------- 3 files changed, 85 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 92148a5..f951a22 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,11 @@ This driver exports a few files in its own platform device, msi-ec, and is avail - on: cooler boost function is enabled - off: cooler boost function is disabled +- `/sys/devices/platform/msi-ec/available_shift_modes` + - Description: This entry reports all supported shift modes. + - Access: Read + - Valid values: Newline separated list of strings. + - `/sys/devices/platform/msi-ec/shift_mode` - Description: This entry allows switching the shift mode. It provides a set of profiles for gaining CPU & GPU overclock/underclock. - Access: Read, Write @@ -81,11 +86,6 @@ This driver exports a few files in its own platform device, msi-ec, and is avail - sport: full clock frequency and voltage for the CPU & GPU, aka default desktop mode - turbo: over-voltage and over-clock for the CPU & GPU, aka overclocking mode -- `/sys/devices/platform/msi-ec/available_shift_modes` - - Description: This entry reports all supported shift modes. - - Access: Read - - Valid values: Newline separated list of strings. - - `/sys/devices/platform/msi-ec/super_battery` - Description: This entry allows switching the super battery function. - Access: Read, Write @@ -93,13 +93,20 @@ This driver exports a few files in its own platform device, msi-ec, and is avail - on: super battery function is enabled - off: super battery function is disabled +- `/sys/devices/platform/msi-ec/available_fan_modes` + - Description: This entry reports all supported fan modes. + - Access: Read + - Valid values: Newline separated list of strings. + - `/sys/devices/platform/msi-ec/fan_mode` - Description: This entry allows switching the fan mode. It provides a set of profiles for adjusting the fan speed under specific criteria. - Access: Read, Write - Valid values: - - auto: fan speed adjusts automatically - - basic: fixed 1-level fan speed for CPU/GPU (percent) - - advanced: fixed 6-levels fan speed for CPU/GPU (percent) + - Values reported by `/sys/devices/platform/msi-ec/available_fan_modes`. Some of the possible values: + - auto: fan speed adjusts automatically + - silent: fan is disabled + - basic: fixed 1-level fan speed for CPU/GPU (percent) + - advanced: fixed 6-levels fan speed for CPU/GPU (percent) - `/sys/devices/platform/msi-ec/fw_version` - Description: This entry reports the firmware version of the motherboard. diff --git a/ec_memory_configuration.h b/ec_memory_configuration.h index 42fa748..5d37f3b 100644 --- a/ec_memory_configuration.h +++ b/ec_memory_configuration.h @@ -64,6 +64,8 @@ struct msi_ec_super_battery_conf { struct msi_ec_fan_mode_conf { int address; + struct msi_ec_mode modes[5]; // fixed size for easier hard coding + int modes_count; }; struct msi_ec_cpu_conf { diff --git a/msi-ec.c b/msi-ec.c index 14b0964..44b3241 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -48,6 +48,11 @@ static const char *const SM_COMFORT_NAME = "comfort"; static const char *const SM_SPORT_NAME = "sport"; static const char *const SM_TURBO_NAME = "turbo"; +static const char *const FM_AUTO_NAME = "auto"; +static const char *const FM_SILENT_NAME = "silent"; +static const char *const FM_BASIC_NAME = "basic"; +static const char *const FM_ADVANCED_NAME = "advanced"; + static const char *ALLOWED_FW_0[] __initdata = { "14C1EMS1.101", NULL, @@ -94,6 +99,13 @@ static struct msi_ec_conf CONF0 __initdata = { }, .fan_mode = { .address = 0xf4, + .modes = { + { FM_AUTO_NAME, 0x0d }, + { FM_SILENT_NAME, 0x1d }, + { FM_BASIC_NAME, 0x4d }, + { FM_ADVANCED_NAME, 0x8d } + }, + .modes_count = 4, }, .cpu = { .rt_temp_address = 0x68, @@ -170,6 +182,12 @@ static struct msi_ec_conf CONF1 __initdata = { }, .fan_mode = { .address = 0xf4, + .modes = { + { FM_AUTO_NAME, 0x0d }, + { FM_BASIC_NAME, 0x4d }, + { FM_ADVANCED_NAME, 0x8d } + }, + .modes_count = 3, }, .cpu = { .rt_temp_address = 0x68, @@ -246,6 +264,13 @@ static struct msi_ec_conf CONF2 __initdata = { }, .fan_mode = { .address = 0xd4, + .modes = { + { FM_AUTO_NAME, 0x0d }, + { FM_SILENT_NAME, 0x1d }, + { FM_BASIC_NAME, 0x4d }, + { FM_ADVANCED_NAME, 0x8d } + }, + .modes_count = 4, }, .cpu = { .rt_temp_address = 0x68, @@ -323,6 +348,13 @@ static struct msi_ec_conf CONF3 __initdata = { }, .fan_mode = { .address = 0xd4, + .modes = { + { FM_AUTO_NAME, 0x0d }, + { FM_SILENT_NAME, 0x1d }, + { FM_BASIC_NAME, 0x4d }, + { FM_ADVANCED_NAME, 0x8d } + }, + .modes_count = 4, }, .cpu = { .rt_temp_address = 0x68, @@ -399,6 +431,13 @@ static struct msi_ec_conf CONF4 __initdata = { }, .fan_mode = { .address = 0xd4, + .modes = { + { FM_AUTO_NAME, 0x0d }, + { FM_SILENT_NAME, 0x1d }, + { FM_BASIC_NAME, 0x4d }, + { FM_ADVANCED_NAME, 0x8d } + }, + .modes_count = 4, }, .cpu = { .rt_temp_address = 0x68, @@ -439,18 +478,6 @@ static struct msi_ec_conf *CONFIGURATIONS[] __initdata = { static struct msi_ec_conf conf; // current configuration -#define FAN_MODES_COUNT 4 -static const char *const FM_AUTO_NAME = "auto"; -static const char *const FM_SILENT_NAME = "silent"; -static const char *const FM_BASIC_NAME = "basic"; -static const char *const FM_ADVANCED_NAME = "advanced"; -static const struct msi_ec_mode FAN_MODES[] = { - { FM_AUTO_NAME, 0x0d }, - { FM_SILENT_NAME, 0x1d }, - { FM_BASIC_NAME, 0x4d }, - { FM_ADVANCED_NAME, 0x8d } -}; - struct attribute_support { struct attribute *attribute; bool supported; @@ -1039,6 +1066,23 @@ static ssize_t super_battery_store(struct device *dev, return count; } +static ssize_t available_fan_modes_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + int result = 0; + int count = 0; + + for (int i = 0; i < conf.fan_mode.modes_count; i++) { + result = sprintf(buf + count, "%s\n", conf.fan_mode.modes[i].name); + if (result < 0) + return result; + count += result; + } + + return count; +} + static ssize_t fan_mode_show(struct device *device, struct device_attribute *attr, char *buf) { @@ -1049,9 +1093,9 @@ static ssize_t fan_mode_show(struct device *device, if (result < 0) return result; - for (int i = 0; i < FAN_MODES_COUNT; i++) { - if (rdata == FAN_MODES[i].value) { - return sprintf(buf, "%s\n", FAN_MODES[i].name); + for (int i = 0; i < conf.fan_mode.modes_count; i++) { + if (rdata == conf.fan_mode.modes[i].value) { + return sprintf(buf, "%s\n", conf.fan_mode.modes[i].name); } } @@ -1063,9 +1107,10 @@ static ssize_t fan_mode_store(struct device *dev, struct device_attribute *attr, { int result; - for (int i = 0; i < FAN_MODES_COUNT; i++) { - if (strcmp_trim_newline2(FAN_MODES[i].name, buf) == 0) { - result = ec_write(conf.fan_mode.address, FAN_MODES[i].value); + for (int i = 0; i < conf.fan_mode.modes_count; i++) { + if (strcmp_trim_newline2(conf.fan_mode.modes[i].name, buf) == 0) { + result = ec_write(conf.fan_mode.address, + conf.fan_mode.modes[i].value); if (result < 0) return result; @@ -1126,6 +1171,7 @@ static DEVICE_ATTR_RW(cooler_boost); static DEVICE_ATTR_RO(available_shift_modes); static DEVICE_ATTR_RW(shift_mode); static DEVICE_ATTR_RW(super_battery); +static DEVICE_ATTR_RO(available_fan_modes); static DEVICE_ATTR_RW(fan_mode); static DEVICE_ATTR_RO(fw_version); static DEVICE_ATTR_RO(fw_release_date); @@ -1370,6 +1416,10 @@ static int msi_platform_probe(struct platform_device *pdev) &dev_attr_super_battery.attr, conf.super_battery.address != MSI_EC_ADDR_UNKNOWN, }, + { + &dev_attr_available_fan_modes.attr, + conf.fan_mode.address != MSI_EC_ADDR_UNKNOWN, + }, { &dev_attr_fan_mode.attr, conf.fan_mode.address != MSI_EC_ADDR_UNKNOWN, From d6cc72ffa48cad520b6f94c11ba0edce37659d7f Mon Sep 17 00:00:00 2001 From: teackot Date: Thu, 16 Feb 2023 12:18:50 +0300 Subject: [PATCH 27/28] Remove power_status attributes --- ec_memory_configuration.h | 7 ----- msi-ec.c | 61 --------------------------------------- 2 files changed, 68 deletions(-) diff --git a/ec_memory_configuration.h b/ec_memory_configuration.h index 5d37f3b..0137fcb 100644 --- a/ec_memory_configuration.h +++ b/ec_memory_configuration.h @@ -34,12 +34,6 @@ struct msi_ec_fn_win_swap_conf { int bit; }; -struct msi_ec_power_status_conf { - int address; - int lid_open_bit; - int ac_connected_bit; -}; - struct msi_ec_cooler_boost_conf { int address; int bit; @@ -106,7 +100,6 @@ struct msi_ec_conf { struct msi_ec_charge_control_conf charge_control; struct msi_ec_webcam_conf webcam; struct msi_ec_fn_win_swap_conf fn_win_swap; - struct msi_ec_power_status_conf power_status; struct msi_ec_cooler_boost_conf cooler_boost; struct msi_ec_shift_mode_conf shift_mode; struct msi_ec_super_battery_conf super_battery; diff --git a/msi-ec.c b/msi-ec.c index 44b3241..c660be2 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -76,11 +76,6 @@ static struct msi_ec_conf CONF0 __initdata = { .address = 0xbf, .bit = 4, }, - .power_status = { - .address = 0x30, - .lid_open_bit = 1, - .ac_connected_bit = 0, - }, .cooler_boost = { .address = 0x98, .bit = 7, @@ -158,11 +153,6 @@ static struct msi_ec_conf CONF1 __initdata = { .address = 0xbf, .bit = 4, }, - .power_status = { - .address = 0x30, - .lid_open_bit = 1, - .ac_connected_bit = 0, - }, .cooler_boost = { .address = 0x98, .bit = 7, @@ -240,11 +230,6 @@ static struct msi_ec_conf CONF2 __initdata = { .address = 0xe8, .bit = 4, }, - .power_status = { - .address = 0x30, - .lid_open_bit = 1, - .ac_connected_bit = 0, - }, .cooler_boost = { .address = 0x98, .bit = 7, @@ -324,11 +309,6 @@ static struct msi_ec_conf CONF3 __initdata = { .address = 0xe8, .bit = 4, }, - .power_status = { - .address = 0x30, - .lid_open_bit = 1, - .ac_connected_bit = 0, - }, .cooler_boost = { .address = 0x98, .bit = 7, @@ -407,11 +387,6 @@ static struct msi_ec_conf CONF4 __initdata = { .address = MSI_EC_ADDR_UNKNOWN, // supported, but unknown .bit = 4, }, - .power_status = { - .address = 0x30, - .lid_open_bit = 1, - .ac_connected_bit = 0, - }, .cooler_boost = { .address = 0x98, .bit = 7, @@ -908,32 +883,6 @@ static ssize_t battery_mode_store(struct device *dev, return count; } -static ssize_t lid_status_show(struct device *device, - struct device_attribute *attr, char *buf) -{ - int result; - bool bit_value; - - result = ec_check_bit(conf.power_status.address, conf.power_status.lid_open_bit, &bit_value); - if (result < 0) - return result; - - return sprintf(buf, "%s\n", bit_value ? "open" : "closed"); -} - -static ssize_t ac_connected_show(struct device *device, - struct device_attribute *attr, char *buf) -{ - int result; - bool bit_value; - - result = ec_check_bit(conf.power_status.address, conf.power_status.ac_connected_bit, &bit_value); - if (result < 0) - return result; - - return sprintf(buf, "%s\n", bit_value ? "1" : "0"); -} - static ssize_t cooler_boost_show(struct device *device, struct device_attribute *attr, char *buf) { @@ -1165,8 +1114,6 @@ static DEVICE_ATTR_RW(webcam_block); static DEVICE_ATTR_RW(fn_key); static DEVICE_ATTR_RW(win_key); static DEVICE_ATTR_RW(battery_mode); -static DEVICE_ATTR_RO(lid_status); -static DEVICE_ATTR_RO(ac_connected); static DEVICE_ATTR_RW(cooler_boost); static DEVICE_ATTR_RO(available_shift_modes); static DEVICE_ATTR_RW(shift_mode); @@ -1392,14 +1339,6 @@ static int msi_platform_probe(struct platform_device *pdev) &dev_attr_battery_mode.attr, conf.charge_control.address != MSI_EC_ADDR_UNKNOWN, }, - { - &dev_attr_lid_status.attr, - conf.power_status.address != MSI_EC_ADDR_UNKNOWN, - }, - { - &dev_attr_ac_connected.attr, - conf.power_status.address != MSI_EC_ADDR_UNKNOWN, - }, { &dev_attr_cooler_boost.attr, conf.cooler_boost.address != MSI_EC_ADDR_UNKNOWN, From e71488345ab5059ca1342f2d8703544189360c7b Mon Sep 17 00:00:00 2001 From: teackot Date: Thu, 16 Feb 2023 12:44:21 +0300 Subject: [PATCH 28/28] Omit commas after sentinel entries; use sentinel entries for modes arrays --- ec_memory_configuration.h | 3 +- msi-ec.c | 74 +++++++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/ec_memory_configuration.h b/ec_memory_configuration.h index 0137fcb..a02e8f6 100644 --- a/ec_memory_configuration.h +++ b/ec_memory_configuration.h @@ -39,6 +39,7 @@ struct msi_ec_cooler_boost_conf { int bit; }; +#define MSI_EC_MODE_NULL { NULL, 0 } struct msi_ec_mode { const char *name; int value; @@ -48,7 +49,6 @@ struct msi_ec_mode { struct msi_ec_shift_mode_conf { int address; struct msi_ec_mode modes[5]; // fixed size for easier hard coding - int modes_count; }; struct msi_ec_super_battery_conf { @@ -59,7 +59,6 @@ struct msi_ec_super_battery_conf { struct msi_ec_fan_mode_conf { int address; struct msi_ec_mode modes[5]; // fixed size for easier hard coding - int modes_count; }; struct msi_ec_cpu_conf { diff --git a/msi-ec.c b/msi-ec.c index c660be2..8cf7960 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -55,7 +55,7 @@ static const char *const FM_ADVANCED_NAME = "advanced"; static const char *ALLOWED_FW_0[] __initdata = { "14C1EMS1.101", - NULL, + NULL }; static struct msi_ec_conf CONF0 __initdata = { @@ -86,8 +86,8 @@ static struct msi_ec_conf CONF0 __initdata = { { SM_ECO_NAME, 0xc2 }, { SM_COMFORT_NAME, 0xc1 }, { SM_SPORT_NAME, 0xc0 }, + MSI_EC_MODE_NULL }, - .modes_count = 3, }, .super_battery = { .address = MSI_EC_ADDR_UNKNOWN, @@ -98,9 +98,9 @@ static struct msi_ec_conf CONF0 __initdata = { { FM_AUTO_NAME, 0x0d }, { FM_SILENT_NAME, 0x1d }, { FM_BASIC_NAME, 0x4d }, - { FM_ADVANCED_NAME, 0x8d } + { FM_ADVANCED_NAME, 0x8d }, + MSI_EC_MODE_NULL }, - .modes_count = 4, }, .cpu = { .rt_temp_address = 0x68, @@ -132,7 +132,7 @@ static struct msi_ec_conf CONF0 __initdata = { static const char *ALLOWED_FW_1[] __initdata = { "17F2EMS1.106", - NULL, + NULL }; static struct msi_ec_conf CONF1 __initdata = { @@ -164,8 +164,8 @@ static struct msi_ec_conf CONF1 __initdata = { { SM_COMFORT_NAME, 0xc1 }, { SM_SPORT_NAME, 0xc0 }, { SM_TURBO_NAME, 0xc4 }, + MSI_EC_MODE_NULL }, - .modes_count = 4, }, .super_battery = { .address = MSI_EC_ADDR_UNKNOWN, @@ -175,9 +175,9 @@ static struct msi_ec_conf CONF1 __initdata = { .modes = { { FM_AUTO_NAME, 0x0d }, { FM_BASIC_NAME, 0x4d }, - { FM_ADVANCED_NAME, 0x8d } + { FM_ADVANCED_NAME, 0x8d }, + MSI_EC_MODE_NULL }, - .modes_count = 3, }, .cpu = { .rt_temp_address = 0x68, @@ -209,7 +209,7 @@ static struct msi_ec_conf CONF1 __initdata = { static const char *ALLOWED_FW_2[] __initdata = { "1552EMS1.118", - NULL, + NULL }; static struct msi_ec_conf CONF2 __initdata = { @@ -240,8 +240,8 @@ static struct msi_ec_conf CONF2 __initdata = { { SM_ECO_NAME, 0xc2 }, { SM_COMFORT_NAME, 0xc1 }, { SM_SPORT_NAME, 0xc0 }, + MSI_EC_MODE_NULL }, - .modes_count = 3, }, .super_battery = { .address = 0xeb, @@ -253,9 +253,9 @@ static struct msi_ec_conf CONF2 __initdata = { { FM_AUTO_NAME, 0x0d }, { FM_SILENT_NAME, 0x1d }, { FM_BASIC_NAME, 0x4d }, - { FM_ADVANCED_NAME, 0x8d } + { FM_ADVANCED_NAME, 0x8d }, + MSI_EC_MODE_NULL }, - .modes_count = 4, }, .cpu = { .rt_temp_address = 0x68, @@ -288,7 +288,7 @@ static struct msi_ec_conf CONF2 __initdata = { static const char *ALLOWED_FW_3[] __initdata = { "1592EMS1.111", "E1592IMS.10C", - NULL, + NULL }; static struct msi_ec_conf CONF3 __initdata = { @@ -319,8 +319,8 @@ static struct msi_ec_conf CONF3 __initdata = { { SM_ECO_NAME, 0xc2 }, { SM_COMFORT_NAME, 0xc1 }, { SM_SPORT_NAME, 0xc0 }, + MSI_EC_MODE_NULL }, - .modes_count = 3, }, .super_battery = { .address = 0xeb, @@ -332,9 +332,9 @@ static struct msi_ec_conf CONF3 __initdata = { { FM_AUTO_NAME, 0x0d }, { FM_SILENT_NAME, 0x1d }, { FM_BASIC_NAME, 0x4d }, - { FM_ADVANCED_NAME, 0x8d } + { FM_ADVANCED_NAME, 0x8d }, + MSI_EC_MODE_NULL }, - .modes_count = 4, }, .cpu = { .rt_temp_address = 0x68, @@ -366,7 +366,7 @@ static struct msi_ec_conf CONF3 __initdata = { static const char *ALLOWED_FW_4[] __initdata = { "16V4EMS1.114", - NULL, + NULL }; static struct msi_ec_conf CONF4 __initdata = { @@ -397,8 +397,8 @@ static struct msi_ec_conf CONF4 __initdata = { { SM_ECO_NAME, 0xc2 }, { SM_COMFORT_NAME, 0xc1 }, { SM_SPORT_NAME, 0xc0 }, + MSI_EC_MODE_NULL }, - .modes_count = 3, }, .super_battery = { // supported, but address is unknown .address = MSI_EC_ADDR_UNKNOWN, @@ -410,9 +410,9 @@ static struct msi_ec_conf CONF4 __initdata = { { FM_AUTO_NAME, 0x0d }, { FM_SILENT_NAME, 0x1d }, { FM_BASIC_NAME, 0x4d }, - { FM_ADVANCED_NAME, 0x8d } + { FM_ADVANCED_NAME, 0x8d }, + MSI_EC_MODE_NULL }, - .modes_count = 4, }, .cpu = { .rt_temp_address = 0x68, @@ -448,7 +448,7 @@ static struct msi_ec_conf *CONFIGURATIONS[] __initdata = { &CONF2, &CONF3, &CONF4, - NULL, + NULL }; static struct msi_ec_conf conf; // current configuration @@ -671,7 +671,7 @@ static DEVICE_ATTR_RW(charge_control_end_threshold); static struct attribute *msi_battery_attrs[] = { &dev_attr_charge_control_start_threshold.attr, &dev_attr_charge_control_end_threshold.attr, - NULL, + NULL }; ATTRIBUTE_GROUPS(msi_battery); @@ -925,7 +925,9 @@ static ssize_t available_shift_modes_show(struct device *device, int result = 0; int count = 0; - for (int i = 0; i < conf.shift_mode.modes_count; i++) { + for (int i = 0; conf.shift_mode.modes[i].name; i++) { + // NULL entries have NULL name + result = sprintf(buf + count, "%s\n", conf.shift_mode.modes[i].name); if (result < 0) return result; @@ -949,7 +951,9 @@ static ssize_t shift_mode_show(struct device *device, if (rdata == 0x80) return sprintf(buf, "%s\n", "unspecified"); - for (int i = 0; i < conf.shift_mode.modes_count; i++) { + for (int i = 0; conf.shift_mode.modes[i].name; i++) { + // NULL entries have NULL name + if (rdata == conf.shift_mode.modes[i].value) { return sprintf(buf, "%s\n", conf.shift_mode.modes[i].name); } @@ -964,7 +968,9 @@ static ssize_t shift_mode_store(struct device *dev, { int result; - for (int i = 0; i < conf.shift_mode.modes_count; i++) { + for (int i = 0; conf.shift_mode.modes[i].name; i++) { + // NULL entries have NULL name + if (strcmp_trim_newline2(conf.shift_mode.modes[i].name, buf) == 0) { result = ec_write(conf.shift_mode.address, conf.shift_mode.modes[i].value); @@ -1022,7 +1028,9 @@ static ssize_t available_fan_modes_show(struct device *device, int result = 0; int count = 0; - for (int i = 0; i < conf.fan_mode.modes_count; i++) { + for (int i = 0; conf.fan_mode.modes[i].name; i++) { + // NULL entries have NULL name + result = sprintf(buf + count, "%s\n", conf.fan_mode.modes[i].name); if (result < 0) return result; @@ -1042,7 +1050,9 @@ static ssize_t fan_mode_show(struct device *device, if (result < 0) return result; - for (int i = 0; i < conf.fan_mode.modes_count; i++) { + for (int i = 0; conf.fan_mode.modes[i].name; i++) { + // NULL entries have NULL name + if (rdata == conf.fan_mode.modes[i].value) { return sprintf(buf, "%s\n", conf.fan_mode.modes[i].name); } @@ -1056,7 +1066,9 @@ static ssize_t fan_mode_store(struct device *dev, struct device_attribute *attr, { int result; - for (int i = 0; i < conf.fan_mode.modes_count; i++) { + for (int i = 0; conf.fan_mode.modes[i].name; i++) { + // NULL entries have NULL name + if (strcmp_trim_newline2(conf.fan_mode.modes[i].name, buf) == 0) { result = ec_write(conf.fan_mode.address, conf.fan_mode.modes[i].value); @@ -1237,7 +1249,7 @@ static struct attribute *msi_cpu_attrs[] = { &dev_attr_cpu_realtime_temperature.attr, &dev_attr_cpu_realtime_fan_speed.attr, &dev_attr_cpu_basic_fan_speed.attr, - NULL, + NULL }; static const struct attribute_group msi_cpu_group = { @@ -1296,7 +1308,7 @@ static struct device_attribute dev_attr_gpu_realtime_fan_speed = { static struct attribute *msi_gpu_attrs[] = { &dev_attr_gpu_realtime_temperature.attr, &dev_attr_gpu_realtime_fan_speed.attr, - NULL, + NULL }; static const struct attribute_group msi_gpu_group = { @@ -1310,7 +1322,7 @@ static const struct attribute_group *msi_platform_groups[] = { &msi_root_group, &msi_cpu_group, &msi_gpu_group, - NULL, + NULL }; static int msi_platform_probe(struct platform_device *pdev)