diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index c17b5cb..9dc2764 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -57,6 +57,9 @@ #define UNIWILL_BRIGHTNESS_DEFAULT UNIWILL_BRIGHTNESS_MAX * 0.30 #define UNIWILL_COLOR_DEFAULT 0xffffff +static void uw_charging_priority_write_state(void); +static void uw_charging_profile_write_state(void); + struct tuxedo_keyboard_driver uniwill_keyboard_driver; struct kbd_led_state_uw_t { @@ -380,12 +383,19 @@ void uniwill_event_callb(u32 code) kbd_led_state_uw.brightness = 0xc8; uniwill_write_kbd_bl_state(); break; - // Also refresh keyboard state on cable switch event + // Refresh keyboard state on cable switch event case UNIWILL_OSD_DC_ADAPTER_CHANGE: uniwill_write_kbd_bl_state(); break; } } + + switch (code) { + case UNIWILL_OSD_DC_ADAPTER_CHANGE: + msleep(50); + uw_charging_priority_write_state(); + break; + } } static ssize_t uw_brightness_show(struct device *child, @@ -766,6 +776,35 @@ static int uw_lightbar_remove(struct platform_device *dev) } static bool uw_charging_prio_loaded = false; +static bool uw_charging_prio_last_written_value; + +static ssize_t uw_charging_prios_available_show(struct device *child, + struct device_attribute *attr, + char *buffer); +static ssize_t uw_charging_prio_show(struct device *child, + struct device_attribute *attr, char *buffer); +static ssize_t uw_charging_prio_store(struct device *child, + struct device_attribute *attr, + const char *buffer, size_t size); + +struct uw_charging_prio_attrs_t { + struct device_attribute charging_prios_available; + struct device_attribute charging_prio; +} uw_charging_prio_attrs = { + .charging_prios_available = __ATTR(charging_prios_available, 0444, uw_charging_prios_available_show, NULL), + .charging_prio = __ATTR(charging_prio, 0644, uw_charging_prio_show, uw_charging_prio_store) +}; + +static struct attribute *uw_charging_prio_attrs_list[] = { + &uw_charging_prio_attrs.charging_prios_available.attr, + &uw_charging_prio_attrs.charging_prio.attr, + NULL +}; + +static struct attribute_group uw_charging_prio_attr_group = { + .name = "charging_priority", + .attrs = uw_charging_prio_attrs_list +}; /* * charging_prio values @@ -785,6 +824,8 @@ static int uw_set_charging_priority(u8 charging_priority) next_data = (previous_data & ~(1 << 7)) | charging_priority; result = uniwill_write_ec_ram(0x07cc, next_data); + if (result == 0) + uw_charging_prio_last_written_value = charging_priority; return result; } @@ -821,7 +862,57 @@ static int uw_has_charging_priority(bool *status) return result; } +static void uw_charging_priority_write_state(void) +{ + if (uw_charging_prio_loaded) + uw_set_charging_priority(uw_charging_prio_last_written_value); +} + +static void uw_charging_priority_init(struct platform_device *dev) +{ + u8 value; + struct uniwill_device_features_t *uw_feats = &uniwill_device_features; + + if (uw_feats->uniwill_has_charging_prio) + uw_charging_prio_loaded = sysfs_create_group(&dev->dev.kobj, &uw_charging_prio_attr_group) == 0; + + // Read for state init + if (uw_charging_prio_loaded) { + uw_get_charging_priority(&value); + uw_charging_prio_last_written_value = value; + } +} + static bool uw_charging_profile_loaded = false; +static bool uw_charging_profile_last_written_value; + +static ssize_t uw_charging_profiles_available_show(struct device *child, + struct device_attribute *attr, + char *buffer); +static ssize_t uw_charging_profile_show(struct device *child, + struct device_attribute *attr, char *buffer); +static ssize_t uw_charging_profile_store(struct device *child, + struct device_attribute *attr, + const char *buffer, size_t size); + +struct uw_charging_profile_attrs_t { + struct device_attribute charging_profiles_available; + struct device_attribute charging_profile; +} uw_charging_profile_attrs = { + .charging_profiles_available = __ATTR(charging_profiles_available, 0444, uw_charging_profiles_available_show, NULL), + .charging_profile = __ATTR(charging_profile, 0644, uw_charging_profile_show, uw_charging_profile_store) +}; + +static struct attribute *uw_charging_profile_attrs_list[] = { + &uw_charging_profile_attrs.charging_profiles_available.attr, + &uw_charging_profile_attrs.charging_profile.attr, + NULL +}; + +static struct attribute_group uw_charging_profile_attr_group = { + .name = "charging_profile", + .attrs = uw_charging_profile_attrs_list +}; /* * charging_profile values @@ -843,13 +934,17 @@ static int uw_set_charging_profile(u8 charging_profile) next_data = (previous_data & ~(0x03 << 4)) | charging_profile; result = uniwill_write_ec_ram(0x07a6, next_data); + if (result == 0) + uw_charging_profile_last_written_value = charging_profile; + return result; } static int uw_get_charging_profile(u8 *charging_profile) { int result = uniwill_read_ec_ram(0x07a6, charging_profile); - *charging_profile = (*charging_profile >> 4) & 0x03; + if (result == 0) + *charging_profile = (*charging_profile >> 4) & 0x03; return result; } @@ -878,6 +973,27 @@ static int uw_has_charging_profile(bool *status) return result; } +static void uw_charging_profile_write_state(void) +{ + if (uw_charging_profile_loaded) + uw_set_charging_profile(uw_charging_profile_last_written_value); +} + +static void uw_charging_profile_init(struct platform_device *dev) +{ + u8 value; + struct uniwill_device_features_t *uw_feats = &uniwill_device_features; + + if (uw_feats->uniwill_has_charging_profile) + uw_charging_profile_loaded = sysfs_create_group(&dev->dev.kobj, &uw_charging_profile_attr_group) == 0; + + // Read for state init + if (uw_charging_profile_loaded) { + uw_get_charging_profile(&value); + uw_charging_profile_last_written_value = value; + } +} + struct char_to_u8_t { char* descriptor; u8 value; @@ -960,25 +1076,6 @@ static ssize_t uw_charging_profile_store(struct device *child, return -EINVAL; } -struct uw_charging_profile_attrs_t { - struct device_attribute charging_profiles_available; - struct device_attribute charging_profile; -} uw_charging_profile_attrs = { - .charging_profiles_available = __ATTR(charging_profiles_available, 0444, uw_charging_profiles_available_show, NULL), - .charging_profile = __ATTR(charging_profile, 0644, uw_charging_profile_show, uw_charging_profile_store) -}; - -static struct attribute *uw_charging_profile_attrs_list[] = { - &uw_charging_profile_attrs.charging_profiles_available.attr, - &uw_charging_profile_attrs.charging_profile.attr, - NULL -}; - -static struct attribute_group uw_charging_profile_attr_group = { - .name = "charging_profile", - .attrs = uw_charging_profile_attrs_list -}; - static struct char_to_u8_t charging_prio_options[] = { { .descriptor = "charge_battery", .value = 0x00 }, { .descriptor = "performance", .value = 0x01 } @@ -1055,25 +1152,6 @@ static ssize_t uw_charging_prio_store(struct device *child, return -EINVAL; } -struct uw_charging_prio_attrs_t { - struct device_attribute charging_prios_available; - struct device_attribute charging_prio; -} uw_charging_prio_attrs = { - .charging_prios_available = __ATTR(charging_prios_available, 0444, uw_charging_prios_available_show, NULL), - .charging_prio = __ATTR(charging_prio, 0644, uw_charging_prio_show, uw_charging_prio_store) -}; - -static struct attribute *uw_charging_prio_attrs_list[] = { - &uw_charging_prio_attrs.charging_prios_available.attr, - &uw_charging_prio_attrs.charging_prio.attr, - NULL -}; - -static struct attribute_group uw_charging_prio_attr_group = { - .name = "charging_priority", - .attrs = uw_charging_prio_attrs_list -}; - struct uniwill_device_features_t *uniwill_get_device_features(void) { struct uniwill_device_features_t *uw_feats = &uniwill_device_features; @@ -1172,11 +1250,8 @@ static int uniwill_keyboard_probe(struct platform_device *dev) status = uw_lightbar_init(dev); uw_lightbar_loaded = (status >= 0); - if (uw_feats->uniwill_has_charging_prio) - uw_charging_prio_loaded = sysfs_create_group(&dev->dev.kobj, &uw_charging_prio_attr_group) == 0; - - if (uw_feats->uniwill_has_charging_profile) - uw_charging_profile_loaded = sysfs_create_group(&dev->dev.kobj, &uw_charging_profile_attr_group) == 0; + uw_charging_priority_init(dev); + uw_charging_profile_init(dev); return 0; }