From fd39d6bc014607d43ea8d3366e7b8e7c55938dde Mon Sep 17 00:00:00 2001 From: Fede2782 <78815152+Fede2782@users.noreply.github.com> Date: Fri, 19 Dec 2025 21:07:17 +0100 Subject: [PATCH] Implement USB Powershare feature --- README.md | 7 +++ docs/sysfs-platform-msi-ec | 6 ++ ec_memory_configuration.h | 6 ++ msi-ec.c | 120 +++++++++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+) diff --git a/README.md b/README.md index 4fa9d5a..b607356 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,13 @@ 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/usb_powershare` + - Description: This entry allows enabling the usb powershare function. It provides power to charge devices via USB ports while device is suspended. + - Access: Read, Write + - Valid values: + - on: usb powershare function is enabled + - off: usb powershare function is disabled + - `/sys/devices/platform/msi-ec/available_shift_modes` - Description: This entry reports all supported shift modes. - Access: Read diff --git a/docs/sysfs-platform-msi-ec b/docs/sysfs-platform-msi-ec index 78cd276..0878b98 100644 --- a/docs/sysfs-platform-msi-ec +++ b/docs/sysfs-platform-msi-ec @@ -26,6 +26,12 @@ Description: to the maximum speed for quicker cooling. Valid values: "on", "off". +What: /sys/devices/platform//usb_powershare +Description: + Control the usb powershare feature. This feature enables + usb charging while device is suspended or powered off. + Valid values: "on", "off". + What: /sys/devices/platform//available_shift_modes Description: Read-only, shows the list of available shift modes for diff --git a/ec_memory_configuration.h b/ec_memory_configuration.h index ff9503f..e7aba59 100644 --- a/ec_memory_configuration.h +++ b/ec_memory_configuration.h @@ -33,6 +33,11 @@ struct msi_ec_cooler_boost_conf { int bit; }; +struct msi_ec_usb_powershare_conf { + int address; + int bit; +}; + #define MSI_EC_MODE_NULL { NULL, 0 } struct msi_ec_mode { const char *name; @@ -89,6 +94,7 @@ struct msi_ec_conf { struct msi_ec_webcam_conf webcam; struct msi_ec_fn_win_swap_conf fn_win_swap; struct msi_ec_cooler_boost_conf cooler_boost; + struct msi_ec_usb_powershare_conf usb_powershare; struct msi_ec_shift_mode_conf shift_mode; struct msi_ec_super_battery_conf super_battery; struct msi_ec_fan_mode_conf fan_mode; diff --git a/msi-ec.c b/msi-ec.c index 2461809..aabff80 100644 --- a/msi-ec.c +++ b/msi-ec.c @@ -81,6 +81,10 @@ static struct msi_ec_conf CONF_G1_0 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -164,6 +168,10 @@ static struct msi_ec_conf CONF_G1_1 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -235,6 +243,10 @@ static struct msi_ec_conf CONF_G1_2 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -318,6 +330,10 @@ static struct msi_ec_conf CONF_G1_3 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -388,6 +404,10 @@ static struct msi_ec_conf CONF_G1_4 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -462,6 +482,10 @@ static struct msi_ec_conf CONF_G1_5 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -539,6 +563,10 @@ static struct msi_ec_conf CONF_G1_6 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -620,6 +648,10 @@ static struct msi_ec_conf CONF_G1_7 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -690,6 +722,10 @@ static struct msi_ec_conf CONF_G1_8 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -760,6 +796,10 @@ static struct msi_ec_conf CONF_G1_9 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -828,6 +868,10 @@ static struct msi_ec_conf CONF_G1_10 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -901,6 +945,10 @@ static struct msi_ec_conf CONF_G1_11 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -969,6 +1017,10 @@ static struct msi_ec_conf CONF_G1_13 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xf2, .modes = { @@ -1050,6 +1102,10 @@ static struct msi_ec_conf CONF_G2_0 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = 0xbf, + .bit = 5, + }, .shift_mode = { .address = 0xd2, .modes = { @@ -1171,6 +1227,10 @@ static struct msi_ec_conf CONF_G2_1 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xd2, .modes = { @@ -1260,6 +1320,10 @@ static struct msi_ec_conf CONF_G2_2 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xd2, .modes = { @@ -1350,6 +1414,10 @@ static struct msi_ec_conf CONF_G2_3 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xd2, .modes = { @@ -1419,6 +1487,10 @@ static struct msi_ec_conf CONF_G2_4 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xd2, .modes = { @@ -1490,6 +1562,10 @@ static struct msi_ec_conf CONF_G2_5 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xd2, .modes = { @@ -1572,6 +1648,10 @@ static struct msi_ec_conf CONF_G2_6 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xd2, .modes = { @@ -1710,6 +1790,10 @@ static struct msi_ec_conf CONF_G2_10 __initdata = { .address = 0x98, .bit = 7, }, + .usb_powershare = { + .address = MSI_EC_ADDR_UNKNOWN, + .bit = 5, + }, .shift_mode = { .address = 0xd2, .modes = { @@ -2247,6 +2331,37 @@ static ssize_t cooler_boost_store(struct device *dev, return count; } +static ssize_t usb_powershare_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + int result; + bool value; + + result = ec_check_bit(conf.usb_powershare.address, conf.usb_powershare.bit, &value); + if (result < 0) + return result; + + return sysfs_emit(buf, "%s\n", str_on_off(value)); +} + +static ssize_t usb_powershare_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int result; + bool value; + + result = kstrtobool(buf, &value); + if (result) + return result; + + result = ec_set_bit(conf.usb_powershare.address, conf.usb_powershare.bit, value); + if (result < 0) + return result; + + return count; +} + static ssize_t available_shift_modes_show(struct device *device, struct device_attribute *attr, char *buf) @@ -2466,6 +2581,7 @@ static DEVICE_ATTR_RW(webcam_block); static DEVICE_ATTR_RW(fn_key); static DEVICE_ATTR_RW(win_key); static DEVICE_ATTR_RW(cooler_boost); +static DEVICE_ATTR_RW(usb_powershare); static DEVICE_ATTR_RO(available_shift_modes); static DEVICE_ATTR_RW(shift_mode); static DEVICE_ATTR_RW(super_battery); @@ -2480,6 +2596,7 @@ static struct attribute *msi_root_attrs[] = { &dev_attr_fn_key.attr, &dev_attr_win_key.attr, &dev_attr_cooler_boost.attr, + &dev_attr_usb_powershare.attr, &dev_attr_available_shift_modes.attr, &dev_attr_shift_mode.attr, &dev_attr_super_battery.attr, @@ -2827,6 +2944,9 @@ static umode_t msi_ec_is_visible(struct kobject *kobj, else if (attr == &dev_attr_cooler_boost.attr) address = conf.cooler_boost.address; + else if (attr == &dev_attr_usb_powershare.attr) + address = conf.usb_powershare.address; + else if (attr == &dev_attr_available_shift_modes.attr || attr == &dev_attr_shift_mode.attr) address = conf.shift_mode.address;