power_supply注册节点

power_supply_register注册举例:
 /kernel-4.19-lc/drivers/power/supply/mediatek/battery_common.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
struct ac_data {
    struct power_supply_desc psd;
    struct power_supply *psy;
    int AC_ONLINE;
};

struct usb_data {
    struct power_supply_desc psd;
    struct power_supply *psy;
    int USB_ONLINE;
};

struct battery_data {
    struct power_supply_desc psd;
    struct power_supply *psy;
    int BAT_STATUS;
    int BAT_HEALTH;
    int BAT_PRESENT;
    int BAT_TECHNOLOGY;
    int BAT_CAPACITY;
    /* Add for Battery Service */
    int BAT_batt_vol;
    int BAT_batt_temp;
    int BAT_CURRENT_NOW;
};
 \kernel-4.19-lc\drivers\power\supply\mediatek\battery_common.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
static enum power_supply_property ac_props[] = {
    POWER_SUPPLY_PROP_ONLINE,
};
static enum power_supply_property usb_props[] = {
    POWER_SUPPLY_PROP_ONLINE,
    POWER_SUPPLY_PROP_CURRENT_MAX,
    POWER_SUPPLY_PROP_VOLTAGE_MAX,
    POWER_SUPPLY_PROP_CHARGE_COUNTER
};
static enum power_supply_property battery_props[] = {
    POWER_SUPPLY_PROP_STATUS,
    POWER_SUPPLY_PROP_HEALTH,
    POWER_SUPPLY_PROP_PRESENT,
    POWER_SUPPLY_PROP_TECHNOLOGY,
    POWER_SUPPLY_PROP_CAPACITY,
    /*charging current*/
    POWER_SUPPLY_PROP_CURRENT_NOW,
    /*battery voltage*/
    POWER_SUPPLY_PROP_VOLTAGE_NOW,
    POWER_SUPPLY_PROP_CYCLE_COUNT,
    POWER_SUPPLY_PROP_CURRENT_AVG,
    POWER_SUPPLY_PROP_CHARGE_FULL,
    POWER_SUPPLY_PROP_CHARGE_COUNTER,
    /*bettery temperature*/
    POWER_SUPPLY_PROP_TEMP,
    POWER_SUPPLY_PROP_CAPACITY_LEVEL,
    POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
    POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN
};

/* ac_data initialization */
static struct ac_data ac_main = {
    .psd = {
        .name = "ac",
        .type = POWER_SUPPLY_TYPE_MAINS,
        .properties = ac_props,
        .num_properties = ARRAY_SIZE(ac_props),
        .get_property = ac_get_property,
        },
    .AC_ONLINE = 0,
};
/* usb_data initialization */
static struct usb_data usb_main = {
    .psd = {
        .name = "usb",
        .type = POWER_SUPPLY_TYPE_USB,
        .properties = usb_props,
        .num_properties = ARRAY_SIZE(usb_props),
        .get_property = usb_get_property,
        },
    .USB_ONLINE = 0,
};
/* battery_data initialization */
static struct battery_data battery_main = {
    .psd = {
        .name = "battery",
        .type = POWER_SUPPLY_TYPE_BATTERY,
        .properties = battery_props,
        .num_properties = ARRAY_SIZE(battery_props),
        .get_property = battery_get_property,
        },
    .BAT_STATUS = POWER_SUPPLY_STATUS_DISCHARGING,
    .BAT_HEALTH = POWER_SUPPLY_HEALTH_GOOD,
    .BAT_PRESENT = 1,
    .BAT_TECHNOLOGY = POWER_SUPPLY_TECHNOLOGY_LION,
    .BAT_CAPACITY = 50,
    .BAT_batt_vol = 0,
    .BAT_batt_temp = 0,
};
 \kernel-4.19-lc\drivers\power\supply\mediatek\battery_common.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
static int battery_probe(struct platform_device *dev)
{
    ... ...
    ac_main.psy = power_supply_register(&(dev->dev), &ac_main.psd, NULL);

    usb_main.psy = power_supply_register(&(dev->dev), &usb_main.psd, NULL);

    battery_main.psy = power_supply_register(&(dev->dev), &battery_main.psd, NULL);
    if (IS_ERR(battery_main.psy)) {
        battery_log(BAT_LOG_CRTI, "[BAT_probe] power_supply_register Battery Fail !!\n");
        return ret;
    }
    ... ...
}
====================================================================================================
power_supply_register注册流程详解:
 /kernel-4.19-lc/drivers/power/supply/power_supply_core.c
1
2
3
4
5
6
7
8
9
10
static struct power_supply *__must_check __power_supply_register(struct device *parent, const struct power_supply_desc *desc, const struct power_supply_config *cfg, bool ws)
    struct device *dev;
    struct power_supply *psy;
    dev->class = power_supply_class;
    ... ...
    INIT_WORK(&psy->changed_work, power_supply_changed_work);
    INIT_DELAYED_WORK(&psy->deferred_register_work, power_supply_deferred_register_work);
    rc = device_add(dev);
    ... ...
}
/kernel-4.14/drivers/power/supply/power_supply_sysfs.c
 /kernel-4.14/drivers/power/supply/power_supply_sysfs.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/* Must be in the same order as POWER_SUPPLY_PROP_* */
static struct device_attribute power_supply_attrs[] = {
    /* Properties of type `int' */
    POWER_SUPPLY_ATTR(status),
    POWER_SUPPLY_ATTR(charge_type),
    POWER_SUPPLY_ATTR(health),
    POWER_SUPPLY_ATTR(present),
    POWER_SUPPLY_ATTR(online),
    POWER_SUPPLY_ATTR(authentic),
    POWER_SUPPLY_ATTR(technology),
    POWER_SUPPLY_ATTR(cycle_count),
    POWER_SUPPLY_ATTR(voltage_max),
    POWER_SUPPLY_ATTR(voltage_min),
    POWER_SUPPLY_ATTR(voltage_max_design),
    POWER_SUPPLY_ATTR(voltage_min_design),
    POWER_SUPPLY_ATTR(voltage_now),
    POWER_SUPPLY_ATTR(voltage_avg),
    POWER_SUPPLY_ATTR(voltage_ocv),
    POWER_SUPPLY_ATTR(voltage_boot),
    POWER_SUPPLY_ATTR(current_max),
    POWER_SUPPLY_ATTR(current_now),
    POWER_SUPPLY_ATTR(current_avg),
    POWER_SUPPLY_ATTR(current_boot),
    POWER_SUPPLY_ATTR(power_now),
    POWER_SUPPLY_ATTR(power_avg),
    POWER_SUPPLY_ATTR(charge_full_design),
    POWER_SUPPLY_ATTR(charge_empty_design),
    POWER_SUPPLY_ATTR(charge_full),
    POWER_SUPPLY_ATTR(charge_empty),
    POWER_SUPPLY_ATTR(charge_now),
    POWER_SUPPLY_ATTR(charge_avg),
    POWER_SUPPLY_ATTR(charge_counter),
    POWER_SUPPLY_ATTR(constant_charge_current),
    POWER_SUPPLY_ATTR(constant_charge_current_max),
    POWER_SUPPLY_ATTR(constant_charge_voltage),
    POWER_SUPPLY_ATTR(constant_charge_voltage_max),
    POWER_SUPPLY_ATTR(charge_control_limit),
    POWER_SUPPLY_ATTR(charge_control_limit_max),
    POWER_SUPPLY_ATTR(input_current_limit),
    POWER_SUPPLY_ATTR(energy_full_design),
    POWER_SUPPLY_ATTR(energy_empty_design),
    POWER_SUPPLY_ATTR(energy_full),
    POWER_SUPPLY_ATTR(energy_empty),
    POWER_SUPPLY_ATTR(energy_now),
    POWER_SUPPLY_ATTR(energy_avg),
    POWER_SUPPLY_ATTR(capacity),
    POWER_SUPPLY_ATTR(capacity_alert_min),
    POWER_SUPPLY_ATTR(capacity_alert_max),
    POWER_SUPPLY_ATTR(capacity_level),
    POWER_SUPPLY_ATTR(temp),
    POWER_SUPPLY_ATTR(temp_max),
    POWER_SUPPLY_ATTR(temp_min),
    POWER_SUPPLY_ATTR(temp_alert_min),
    POWER_SUPPLY_ATTR(temp_alert_max),
    POWER_SUPPLY_ATTR(temp_ambient),
    POWER_SUPPLY_ATTR(temp_ambient_alert_min),
    POWER_SUPPLY_ATTR(temp_ambient_alert_max),
    POWER_SUPPLY_ATTR(time_to_empty_now),
    POWER_SUPPLY_ATTR(time_to_empty_avg),
    POWER_SUPPLY_ATTR(time_to_full_now),
    POWER_SUPPLY_ATTR(time_to_full_avg),
    POWER_SUPPLY_ATTR(type),
    POWER_SUPPLY_ATTR(scope),
    POWER_SUPPLY_ATTR(precharge_current),
    POWER_SUPPLY_ATTR(charge_term_current),
    POWER_SUPPLY_ATTR(calibrate),
    /* Local extensions */
    POWER_SUPPLY_ATTR(usb_hc),
    POWER_SUPPLY_ATTR(usb_otg),
    POWER_SUPPLY_ATTR(charge_enabled),
    /* Local extensions of type int64_t */
    POWER_SUPPLY_ATTR(charge_counter_ext),
    /* Properties of type `const char *' */
    POWER_SUPPLY_ATTR(model_name),
    POWER_SUPPLY_ATTR(manufacturer),
    POWER_SUPPLY_ATTR(serial_number),
};
struct device_attribute power_supply_attrs[]和enum power_supply_property 一一对应,
power_supply_register会根据具体的properties(比如enum power_supply_property battery_props)创建对应的attrs
batterymonitor.cpp读取对应的节点时,会调用power_supply_show_property(struct device *dev, struct device_attribute *attr, char *buf)
形参struct device_attribute *attr就是对应property(比如POWER_SUPPLY_PROP_STATUS)所对应的指针,
enum power_supply_property psp = attr - power_supply_attrs;  //计算指针的偏移,得出是第几个property,battery_common.c中的battery_get_property()可以依此执行不同的case
/kernel-4.19-lc/include/linux/power_supply.h
 ... ...
};
/kernel-4.19-lc/drivers/power/supply/power_supply_sysfs.c
static struct attribute_group power_supply_attr_group = {
	.attrs = __power_supply_attrs,  //struct attribute  **attrs;
	.is_visible = power_supply_attr_is_visible,  //umode_t  (*is_visible)(struct kobject *, struct attribute *, int);
};
/kernel-4.19-lc/drivers/power/supply/power_supply_core.c
 
   
static int __init power_supply_class_init(void) { power_supply_class = class_create(THIS_MODULE, "power_supply"); power_supply_class->dev_uevent = power_supply_uevent; power_supply_init_attrs(&power_supply_dev_type);
 ->dev_type->groups = power_supply_attr_groups;    //定义了所有属性的power_supply_*
 
   
 ->for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++)
   ->__power_supply_attrs[i] = &power_supply_attrs[i].attr;
 return 0;
 
   
}
/kernel-4.19-lc/drivers/base/core.c
static const struct kset_uevent_ops device_uevent_ops = {
	.filter =	dev_uevent_filter,
	.name =		dev_uevent_name,
	.uevent =	dev_uevent,
};


struct power_supply *__must_check power_supply_register(struct device *parent, const struct power_supply_desc *desc, const struct power_supply_config *cfg)
static struct power_supply *__must_check __power_supply_register(struct device *parent, const struct power_supply_desc *desc, const struct power_supply_config *cfg, bool ws)
 
   
 ->struct power_supply *psy;
 ->psy = kzalloc(sizeof(*psy), GFP_KERNEL);
 ->dev = &psy->dev;
 ->device_initialize(dev);
 ->dev->class = power_supply_class;
 ->dev->type = &power_supply_dev_type;
 ->dev->parent = parent;
 ->dev->release = power_supply_dev_release;
 ->dev_set_drvdata(dev, psy);
  ->dev->driver_data = data; //psy
 ->psy->desc = desc;
 ->device_add(dev);
  ->device_create_file(dev, &dev_attr_uevent);
  ->device_add_attrs(dev);
   ->struct class *class = dev->class;
   ->const struct device_type *type = dev->type;
   ->if (class) {
    ->device_add_groups(dev, class->dev_groups);  
     ->sysfs_create_groups(&dev->kobj, groups);
      ->if (!groups)    //power_supply_class->groups 为空,所以直接return
       return 0;
 
   
  ->if (type) {
   ->device_add_groups(dev, type->groups); //power_supply_dev_type->groups
 
   
     ->sysfs_create_groups(&dev->kobj, groups);  //power_supply_attr_groups
      ->for (i = 0; groups[i]; i++) {  //只有1个
       ->sysfs_create_group(kobj, groups[i]);
        ->internal_create_group(kobj, 0, grp);
         ->create_files(kn, kobj, uid, gid, grp, update);
          ->if (grp->attrs) {
           ->for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) { //power_supply_attrs
            ->umode_t mode = (*attr)->mode;    //遍历power_supply_attrs中的i
            ->mode = grp->is_visible(kobj, *attr, i); //attr没有用
             ->struct device *dev = container_of(kobj, struct device, kobj);
             ->struct power_supply *psy = dev_get_drvdata(dev);
             ->for (i = 0; i < psy->desc->num_properties; i++) { //查找具体的psy中是否存在枚举i
              ->int property = psy->desc->properties[i];
              ->if (property == attrno) { //i
               ->return mode;
 
   
            ->if (!mode)  //如果不存在,则调过
 
   
                                         continue;
            ->sysfs_create_file_ns(kobj, attr, NULL); //如果存在,则创建相应的sysfs
 
   
  ->device_add_groups(dev, dev->groups);

 
   
device_add最终会跑到create_files,到sys对应的目录下创建文件
dev->class = power_supply_class;
device属于power_supply_class下的设备,遍历grp里的所有属性,如果device的属性is_visible(能返回匹配的属性枚举mode),便调用sysfs_add_file_mode_ns()创建相应的sysfs文件

 /kernel-4.19-lc/fs/sysfs/group.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
static int create_files(struct kernfs_node *parent, struct kobject *kobj,
            kuid_t uid, kgid_t gid,
            const struct attribute_group *grp, int update)
{
    struct attribute *const *attr;
    struct bin_attribute *const *bin_attr;
    int error = 0, i;

    if (grp->attrs) {
        for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
            umode_t mode = (*attr)->mode;

            /*
             * In update mode, we're changing the permissions or
             * visibility.  Do this by first removing then
             * re-adding (if required) the file.
             */

            if (update)
                kernfs_remove_by_name(parent, (*attr)->name);
            if (grp->is_visible) {
                mode = grp->is_visible(kobj, *attr, i);
                if (!mode)
                    continue;
            }

            WARN(mode & ~(SYSFS_PREALLOC | 0664),
                 "Attribute %s: Invalid permissions 0%o\n",
                 (*attr)->name, mode);

            mode &= SYSFS_PREALLOC | 0664;
            error = sysfs_add_file_mode_ns(parent, *attr, false,
                               mode, uid, gid, NULL);
            if (unlikely(error))
                break;
        }
        if (error) {
            remove_files(parent, grp);
            goto exit;
        }
    }

    if (grp->bin_attrs) {
        for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) {
            umode_t mode = (*bin_attr)->attr.mode;

            if (update)
                kernfs_remove_by_name(parent,
                        (*bin_attr)->attr.name);
            if (grp->is_bin_visible) {
                mode = grp->is_bin_visible(kobj, *bin_attr, i);
                if (!mode)
                    continue;
            }

            WARN(mode & ~(SYSFS_PREALLOC | 0664),
                 "Attribute %s: Invalid permissions 0%o\n",
                 (*bin_attr)->attr.name, mode);

            mode &= SYSFS_PREALLOC | 0664;
            error = sysfs_add_file_mode_ns(parent,
                    &(*bin_attr)->attr, true,
                    mode,
                    uid, gid, NULL);
            if (error)
                break;
        }
        if (error)
            remove_files(parent, grp);
    }
exit:
    return error;
}

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值