#include #include #include #include #include #include // 模块相关 #include #include struct virtual_battery_data { struct power_supply *psy; int voltage_now; int current_now; int capacity; int energy_full_design; int energy_full; int energy_now; int status; int temperature; int online; int power_now; int charge_counter; }; struct virtual_adapter_data { struct power_supply *psy; int online; int type; }; // 主数据结构,包含两个子结构 struct virtual_main_data { struct virtual_battery_data battery_data; struct virtual_adapter_data adapter_data; }; static enum power_supply_property virtual_battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, POWER_SUPPLY_PROP_ENERGY_FULL, POWER_SUPPLY_PROP_ENERGY_NOW, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_POWER_NOW, POWER_SUPPLY_PROP_CHARGE_COUNTER, }; static enum power_supply_property virtual_adapter_props[] = { POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_TYPE, // 类型为AC }; //static struct power_supply *virtual_battery; //static struct kobject *battery_kobj; // Sysfs 属性操作 //static ssize_t charge_counter_show(struct kobject *kobj, // struct kobj_attribute *attr, char *buf) /* static ssize_t charge_counter_show(struct device *dev, struct device_attribute *attr, char *buf) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); return sprintf(buf, "%d\n", data->charge_counter); } static ssize_t charge_counter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); int ret; ret = kstrtouint(buf, 10, &data->charge_counter); if (ret < 0) return ret; // 限制范围 0-100 data->charge_counter = clamp_val(data->charge_counter, 0, 24000000); // 通知电源子系统更新 power_supply_changed(psy); return count; } static ssize_t voltage_now_show(struct device *dev, struct device_attribute *attr, char *buf) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); return sprintf(buf, "%d\n", data->voltage_now); } static ssize_t voltage_now_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); int ret; ret = kstrtouint(buf, 10, &data->voltage_now); if (ret < 0) return ret; // 限制范围 0-100 data->voltage_now = clamp_val(data->voltage_now, 0, 24000000); data->power_now = (data->current_now * data->voltage_now)/1000000; // 通知电源子系统更新 power_supply_changed(psy); return count; } static ssize_t energy_now_show(struct device *dev, struct device_attribute *attr, char *buf) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); return sprintf(buf, "%d\n", data->energy_now); } static ssize_t energy_now_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); int ret; ret = kstrtouint(buf, 10, &data->energy_now); if (ret < 0) return ret; // 限制范围 0-100 data->energy_now = clamp_val(data->energy_now, 0, 2000000000); // 通知电源子系统更新 power_supply_changed(psy); return count; } static ssize_t energy_full_show(struct device *dev, struct device_attribute *attr, char *buf) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); return sprintf(buf, "%d\n", data->energy_full); } static ssize_t energy_full_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); int ret; ret = kstrtouint(buf, 10, &data->energy_full); if (ret < 0) return ret; // 限制范围 0-100 data->energy_full = clamp_val(data->energy_full, 0, 2000000000); // 通知电源子系统更新 power_supply_changed(psy); return count; } static ssize_t energy_full_design_show(struct device *dev, struct device_attribute *attr, char *buf) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); return sprintf(buf, "%d\n", data->energy_full_design); } #if 0 static ssize_t energy_full_design_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_data *data = power_supply_get_drvdata(psy); int ret; ret = kstrtouint(buf, 10, &data->energy_full_design); if (ret < 0) return ret; // 限制范围 0-100 data->energy_full_design = clamp_val(data->energy_full_design, 0, 2000000000); // 通知电源子系统更新 power_supply_changed(data); return count; } #endif static ssize_t current_now_show(struct device *dev, struct device_attribute *attr, char *buf) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); return sprintf(buf, "%d\n", data->current_now); } static ssize_t current_now_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); int ret; ret = kstrtouint(buf, 10, &data->current_now); if (ret < 0) return ret; // 限制范围 0-100 data->current_now = clamp_val(data->current_now, 0, 3000000); data->power_now = (data->current_now * data->voltage_now)/1000000; // 通知电源子系统更新 power_supply_changed(psy); return count; } static ssize_t capacity_show(struct device *dev, struct device_attribute *attr, char *buf) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); return sprintf(buf, "%d\n", data->capacity); } static ssize_t capacity_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); int ret; ret = kstrtouint(buf, 10, &data->capacity); if (ret < 0) return ret; // 限制范围 0-100 data->capacity = clamp_val(data->capacity, 0, 100); // 通知电源子系统更新 power_supply_changed(psy); return count; } static ssize_t power_now_show(struct device *dev, struct device_attribute *attr, char *buf) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); return sprintf(buf, "%d\n", data->power_now); } static ssize_t power_now_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_data *data = power_supply_get_drvdata(psy); int ret; ret = kstrtouint(buf, 10, &data->power_now); if (ret < 0) return ret; // 限制范围 0-100 data->capacity = clamp_val(data->power_now, 0, 20000000); // 通知电源子系统更新 power_supply_changed(data); return count; } static ssize_t status_show(struct device *dev, struct device_attribute *attr, char *buf) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); const char *status_str; switch (data->status) { case POWER_SUPPLY_STATUS_CHARGING: status_str = "Charging"; break; case POWER_SUPPLY_STATUS_DISCHARGING: status_str = "Discharging"; break; case POWER_SUPPLY_STATUS_FULL: status_str = "Full"; break; case POWER_SUPPLY_STATUS_NOT_CHARGING: status_str = "Not Charging"; break; default: status_str = "Unknown"; } return sprintf(buf, "%s\n", status_str); } static ssize_t status_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_battery_data *data = power_supply_get_drvdata(psy); if (sysfs_streq(buf, "Charging")) { data->status = POWER_SUPPLY_STATUS_CHARGING; } else if (sysfs_streq(buf, "Discharging")) { data->status = POWER_SUPPLY_STATUS_DISCHARGING; } else if (sysfs_streq(buf, "Full")) { data->status = POWER_SUPPLY_STATUS_FULL; } else if (sysfs_streq(buf, "Not Charging")) { data->status = POWER_SUPPLY_STATUS_NOT_CHARGING; } else { return -EINVAL; } power_supply_changed(psy); return count; } */ // 定义 sysfs 属性 /* static struct kobj_attribute capacity_attr = __ATTR(capacity, 0664, capacity_show, capacity_store); static struct kobj_attribute status_attr = __ATTR(status, 0664, status_show, status_store); static struct kobj_attribute current_attr = __ATTR(current_now, 0664, current_show, current_store); static struct kobj_attribute energy_full_design_attr = __ATTR(energy_full_design, 0664, energy_full_design_show, energy_full_design_store); static struct kobj_attribute energy_full_attr = __ATTR(energy_full, 0664, energy_full_show, energy_full_store); static struct kobj_attribute energy_attr = __ATTR(energy_now, 0664, energy_show, energy_store); static struct kobj_attribute voltage_attr = __ATTR(voltage, 0664, voltage_show, voltage_store); static struct kobj_attribute charge_counter_attr = __ATTR(charge_counter, 0664, charge_counter_show, charge_counter_store); static struct attribute *battery_attrs[] = { &capacity_attr.attr, &status_attr.attr, ¤t_attr.attr, &energy_full_design_attr.attr, &energy_full_attr.attr, &energy_attr.attr, &voltage_attr.attr, &charge_counter_attr.attr, NULL, }; static struct attribute_group battery_attr_group = { .attrs = battery_attrs, }; static DEVICE_ATTR_RW(capacity); static DEVICE_ATTR_RW(status); static DEVICE_ATTR_RW(current_now); static DEVICE_ATTR_RW(voltage_now); static DEVICE_ATTR_RO(energy_full_design); static DEVICE_ATTR_RW(energy_full); static DEVICE_ATTR_RW(energy_now); static DEVICE_ATTR_RW(charge_counter); static DEVICE_ATTR_RO(power_now); static struct attribute *virtual_battery_attrs[] = { &dev_attr_capacity.attr, &dev_attr_status.attr, &dev_attr_current_now.attr, &dev_attr_voltage_now.attr, &dev_attr_energy_full_design.attr, &dev_attr_energy_full.attr, &dev_attr_energy_now.attr, &dev_attr_charge_counter.attr, &dev_attr_power_now.attr, NULL, }; ATTRIBUTE_GROUPS(virtual_battery); // 导出到用户空间的sysfs接口 static ssize_t online_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_adapter_data *data = power_supply_get_drvdata(psy); int online; if (kstrtoint(buf, 10, &online)) return -EINVAL; data->online = !!online; power_supply_changed(psy); return count; } static ssize_t online_show(struct device *dev, struct device_attribute *attr, char *buf) { struct power_supply *psy = dev_get_drvdata(dev); struct virtual_adapter_data *data = power_supply_get_drvdata(psy); return sprintf(buf, "%d\n", data->online); } static DEVICE_ATTR_RW(online); static struct attribute *virtual_adapter_attrs[] = { &dev_attr_online.attr, NULL, }; ATTRIBUTE_GROUPS(virtual_adapter); */ static int virtual_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { struct virtual_battery_data *data = power_supply_get_drvdata(psy); switch (psp) { case POWER_SUPPLY_PROP_VOLTAGE_NOW: val->intval = data->voltage_now; break; case POWER_SUPPLY_PROP_CURRENT_NOW: if (data->status == POWER_SUPPLY_STATUS_CHARGING) val->intval = data->current_now; else { val->intval = -(data->current_now); } break; case POWER_SUPPLY_PROP_CAPACITY: val->intval = data->capacity; break; case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: val->intval = data->energy_full_design; break; case POWER_SUPPLY_PROP_ENERGY_FULL: val->intval = data->energy_full; break; case POWER_SUPPLY_PROP_ENERGY_NOW: val->intval = data->capacity/100*data->energy_full; break; case POWER_SUPPLY_PROP_STATUS: val->intval = data->status; break; case POWER_SUPPLY_PROP_TEMP: val->intval = data->temperature * 10; // 内核温度单位为 0.1°C break; case POWER_SUPPLY_PROP_CHARGE_COUNTER: val->intval = data->charge_counter; break; case POWER_SUPPLY_PROP_HEALTH: val->intval = POWER_SUPPLY_HEALTH_GOOD; break; case POWER_SUPPLY_PROP_POWER_NOW: val->intval = data->power_now; break; default: return -EINVAL; } return 0; } static int virtual_battery_set_property(struct power_supply *psy, enum power_supply_property psp, const union power_supply_propval *val) { struct virtual_battery_data *data = power_supply_get_drvdata(psy); int64_t power; switch (psp) { case POWER_SUPPLY_PROP_CAPACITY: // 验证值范围 if (val->intval < 0 || val->intval > 100) { dev_err(&psy->dev, "Invalid capacity value: %d\n", val->intval); return -EINVAL; } data->capacity = val->intval; break; case POWER_SUPPLY_PROP_STATUS: if (val->intval < POWER_SUPPLY_STATUS_UNKNOWN || val->intval > POWER_SUPPLY_STATUS_FULL) { dev_err(&psy->dev, "Invalid status value: %d\n", val->intval); return -EINVAL; } data->status = val->intval; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: // 验证电压值(单位:微伏) if (val->intval < 0 || val->intval > 13000000) { // 0-13V dev_err(&psy->dev, "Invalid voltage: %d µV\n", val->intval); return -EINVAL; } data->voltage_now = val->intval; power = (int64_t)data->voltage_now * abs(data->current_now); data->power_now = (int)(power / 1000000); dev_dbg( &psy->dev, "voltage_now: %d µV,current: %d µA,power:%lld,power_now:%d\n", data->voltage_now, data->current_now, power, data->power_now); break; case POWER_SUPPLY_PROP_CURRENT_NOW: // 电流可以是正(充电)或负(放电) if (val->intval < -5000000 || val->intval > 5000000) { // -5A to 5A dev_err(&psy->dev, "Invalid current: %d µA\n", val->intval); return -EINVAL; } data->current_now = val->intval; power = (int64_t)data->voltage_now * abs(data->current_now); data->power_now = (int)(power / 1000000); dev_dbg( &psy->dev, "voltage_now: %d µV,current: %d µA,power:%lld,power_now:%d\n", data->voltage_now, data->current_now, power, data->power_now); break; case POWER_SUPPLY_PROP_TEMP: // 温度单位是 0.1°C if (val->intval < -200 || val->intval > 1000) { // -20°C 到 100°C return -EINVAL; } data->temperature = val->intval; break; case POWER_SUPPLY_PROP_ENERGY_NOW: if (val->intval < 0) { dev_err(&psy->dev, "Invalid energy: %d µWh\n", val->intval); return -EINVAL; } data->energy_now = val->intval; break; default: // 对于不支持写的属性返回错误 dev_dbg(&psy->dev, "Property %d is read-only\n", psp); return -EINVAL; } // 通知属性已更改 power_supply_changed(psy); return 0; } static int virtual_battery_property_is_writeable(struct power_supply *psy, enum power_supply_property psp) { // 指定哪些属性可写 switch (psp) { case POWER_SUPPLY_PROP_CAPACITY: case POWER_SUPPLY_PROP_STATUS: case POWER_SUPPLY_PROP_VOLTAGE_NOW: case POWER_SUPPLY_PROP_CURRENT_NOW: case POWER_SUPPLY_PROP_ENERGY_NOW: case POWER_SUPPLY_PROP_TEMP: return 1; // 可写 default: return 0; // 只读 } } static int virtual_adapter_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { struct virtual_adapter_data *data = power_supply_get_drvdata(psy); switch (psp) { case POWER_SUPPLY_PROP_ONLINE: val->intval = data->online; break; case POWER_SUPPLY_PROP_TYPE: val->intval = POWER_SUPPLY_TYPE_MAINS; // 交流电源 break; default: return -EINVAL; } return 0; } static int virtual_adapter_set_property(struct power_supply *psy, enum power_supply_property psp, const union power_supply_propval *val) { struct virtual_adapter_data *data = power_supply_get_drvdata(psy); switch (psp) { case POWER_SUPPLY_PROP_ONLINE: data->online = val->intval ? 1 : 0; break; default: dev_dbg(&psy->dev, "Adapter property %d is read-only\n", psp); return -EINVAL; } // 通知适配器状态变化 power_supply_changed(psy); return 0; } static int virtual_adapter_property_is_writeable(struct power_supply *psy, enum power_supply_property psp) { // 指定哪些属性可写 switch (psp) { case POWER_SUPPLY_PROP_ONLINE: return 1; // 可写 default: return 0; // 只读 } } static const struct power_supply_desc virtual_battery_desc = { .name = "virtual_battery", .type = POWER_SUPPLY_TYPE_BATTERY, .properties = virtual_battery_props, .num_properties = ARRAY_SIZE(virtual_battery_props), .get_property = virtual_battery_get_property, .set_property = virtual_battery_set_property, .property_is_writeable = virtual_battery_property_is_writeable, }; static const struct power_supply_desc virtual_adapter_desc = { .name = "virtual_adapter", .type = POWER_SUPPLY_TYPE_MAINS, .properties = virtual_adapter_props, .num_properties = ARRAY_SIZE(virtual_adapter_props), .get_property = virtual_adapter_get_property, .set_property = virtual_adapter_set_property, .property_is_writeable = virtual_adapter_property_is_writeable, }; static int virtual_battery_probe(struct platform_device *pdev) { struct virtual_main_data *main_data; struct power_supply_config psy_cfg = {}; main_data = devm_kzalloc(&pdev->dev, sizeof(*main_data), GFP_KERNEL); if (!main_data) return -ENOMEM; of_property_read_u32(pdev->dev.of_node, "temperature-celsius", &main_data->battery_data.temperature); of_property_read_u32(pdev->dev.of_node, "energy-full-design-microwatt-hours", &main_data->battery_data.energy_full_design); of_property_read_u32(pdev->dev.of_node, "energy-full-microwatt-hours", &main_data->battery_data.energy_full); of_property_read_u32(pdev->dev.of_node, "capacity-now", &main_data->battery_data.capacity); main_data->battery_data.charge_counter = 0; main_data->battery_data.current_now = 0; main_data->battery_data.voltage_now = 12600000; main_data->battery_data.energy_now = 15000000; main_data->battery_data.power_now = 0; main_data->battery_data.status = POWER_SUPPLY_STATUS_DISCHARGING; psy_cfg.drv_data = &main_data->battery_data; //psy_cfg.attr_grp = virtual_battery_groups; main_data->battery_data.psy = devm_power_supply_register( &pdev->dev, &virtual_battery_desc, &psy_cfg); if (IS_ERR(main_data->battery_data.psy)) { dev_err(&pdev->dev, "Failed to register battery power supply\n"); return PTR_ERR(main_data->battery_data.psy); } main_data->adapter_data.online = 0; psy_cfg.drv_data = &main_data->adapter_data; //psy_cfg.attr_grp = virtual_adapter_groups; main_data->adapter_data.psy = devm_power_supply_register( &pdev->dev, &virtual_adapter_desc, &psy_cfg); if (IS_ERR(main_data->adapter_data.psy)) { dev_err(&pdev->dev, "Failed to register adapter power supply\n"); return PTR_ERR(main_data->adapter_data.psy); } platform_set_drvdata(pdev, main_data); /* // 创建 sysfs 接口 battery_kobj = kobject_create_and_add("virtual_battery", kernel_kobj->parent); if (!battery_kobj) { power_supply_unregister(virtual_battery); return -ENOMEM; } ret = sysfs_create_group(battery_kobj, &battery_attr_group); if (ret) { kobject_put(battery_kobj); power_supply_unregister(virtual_battery); } */ dev_info(&pdev->dev, "Virtual battery probed successfully\n"); return 0; } static int virtual_battery_remove(struct platform_device *pdev) { dev_info(&pdev->dev, "Virtual battery removed\n"); //sysfs_remove_group(battery_kobj, &battery_attr_group); //kobject_put(battery_kobj); return 0; } static const struct of_device_id virtual_battery_of_match[] = { { .compatible = "my-vendor,virtual-battery" }, {}, }; MODULE_DEVICE_TABLE(of, virtual_battery_of_match); static struct platform_driver virtual_battery_driver = { .probe = virtual_battery_probe, .remove = virtual_battery_remove, .driver = { .name = "virtual_battery", .of_match_table = virtual_battery_of_match, }, }; module_platform_driver(virtual_battery_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ardu"); MODULE_DESCRIPTION("Virtual Battery Driver"); MODULE_VERSION("1.0");