Mention branches and keyring.
[releases.git] / thermal / events.c
1 // SPDX-License-Identifier: LGPL-2.1+
2 // Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
3 #include <linux/netlink.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7
8
9 #include <thermal.h>
10 #include "thermal_nl.h"
11
12 /*
13  * Optimization: fill this array to tell which event we do want to pay
14  * attention to. That happens at init time with the ops
15  * structure. Each ops will enable the event and the general handler
16  * will be able to discard the event if there is not ops associated
17  * with it.
18  */
19 static int enabled_ops[__THERMAL_GENL_EVENT_MAX];
20
21 static int handle_thermal_event(struct nl_msg *n, void *arg)
22 {
23         struct nlmsghdr *nlh = nlmsg_hdr(n);
24         struct genlmsghdr *genlhdr = genlmsg_hdr(nlh);
25         struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
26         struct thermal_handler_param *thp = arg;
27         struct thermal_events_ops *ops = &thp->th->ops->events;
28
29         genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL);
30
31         arg = thp->arg;
32
33         /*
34          * This is an event we don't care of, bail out.
35          */
36         if (!enabled_ops[genlhdr->cmd])
37                 return THERMAL_SUCCESS;
38
39         switch (genlhdr->cmd) {
40
41         case THERMAL_GENL_EVENT_TZ_CREATE:
42                 return ops->tz_create(nla_get_string(attrs[THERMAL_GENL_ATTR_TZ_NAME]),
43                                       nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
44
45         case THERMAL_GENL_EVENT_TZ_DELETE:
46                 return ops->tz_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
47
48         case THERMAL_GENL_EVENT_TZ_ENABLE:
49                 return ops->tz_enable(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
50
51         case THERMAL_GENL_EVENT_TZ_DISABLE:
52                 return ops->tz_disable(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
53
54         case THERMAL_GENL_EVENT_TZ_TRIP_CHANGE:
55                 return ops->trip_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
56                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
57                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]),
58                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]),
59                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]), arg);
60
61         case THERMAL_GENL_EVENT_TZ_TRIP_ADD:
62                 return ops->trip_add(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
63                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
64                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]),
65                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]),
66                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]), arg);
67
68         case THERMAL_GENL_EVENT_TZ_TRIP_DELETE:
69                 return ops->trip_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
70                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]), arg);
71
72         case THERMAL_GENL_EVENT_TZ_TRIP_UP:
73                 return ops->trip_high(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
74                                       nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
75                                       nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
76
77         case THERMAL_GENL_EVENT_TZ_TRIP_DOWN:
78                 return ops->trip_low(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
79                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
80                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
81
82         case THERMAL_GENL_EVENT_CDEV_ADD:
83                 return ops->cdev_add(nla_get_string(attrs[THERMAL_GENL_ATTR_CDEV_NAME]),
84                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]),
85                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_MAX_STATE]), arg);
86
87         case THERMAL_GENL_EVENT_CDEV_DELETE:
88                 return ops->cdev_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]), arg);
89
90         case THERMAL_GENL_EVENT_CDEV_STATE_UPDATE:
91                 return ops->cdev_update(nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]),
92                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_CUR_STATE]), arg);
93
94         case THERMAL_GENL_EVENT_TZ_GOV_CHANGE:
95                 return ops->gov_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
96                                        nla_get_string(attrs[THERMAL_GENL_ATTR_GOV_NAME]), arg);
97         default:
98                 return -1;
99         }
100 }
101
102 static void thermal_events_ops_init(struct thermal_events_ops *ops)
103 {
104         enabled_ops[THERMAL_GENL_EVENT_TZ_CREATE]       = !!ops->tz_create;
105         enabled_ops[THERMAL_GENL_EVENT_TZ_DELETE]       = !!ops->tz_delete;
106         enabled_ops[THERMAL_GENL_EVENT_TZ_DISABLE]      = !!ops->tz_disable;
107         enabled_ops[THERMAL_GENL_EVENT_TZ_ENABLE]       = !!ops->tz_enable;
108         enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_UP]      = !!ops->trip_high;
109         enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DOWN]    = !!ops->trip_low;
110         enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_CHANGE]  = !!ops->trip_change;
111         enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_ADD]     = !!ops->trip_add;
112         enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DELETE]  = !!ops->trip_delete;
113         enabled_ops[THERMAL_GENL_EVENT_CDEV_ADD]        = !!ops->cdev_add;
114         enabled_ops[THERMAL_GENL_EVENT_CDEV_DELETE]     = !!ops->cdev_delete;
115         enabled_ops[THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = !!ops->cdev_update;
116         enabled_ops[THERMAL_GENL_EVENT_TZ_GOV_CHANGE]   = !!ops->gov_change;
117 }
118
119 thermal_error_t thermal_events_handle(struct thermal_handler *th, void *arg)
120 {
121         struct thermal_handler_param thp = { .th = th, .arg = arg };
122
123         if (!th)
124                 return THERMAL_ERROR;
125
126         if (nl_cb_set(th->cb_event, NL_CB_VALID, NL_CB_CUSTOM,
127                       handle_thermal_event, &thp))
128                 return THERMAL_ERROR;
129
130         return nl_recvmsgs(th->sk_event, th->cb_event);
131 }
132
133 int thermal_events_fd(struct thermal_handler *th)
134 {
135         if (!th)
136                 return -1;
137
138         return nl_socket_get_fd(th->sk_event);
139 }
140
141 thermal_error_t thermal_events_exit(struct thermal_handler *th)
142 {
143         if (nl_unsubscribe_thermal(th->sk_event, th->cb_event,
144                                    THERMAL_GENL_EVENT_GROUP_NAME))
145                 return THERMAL_ERROR;
146
147         nl_thermal_disconnect(th->sk_event, th->cb_event);
148
149         return THERMAL_SUCCESS;
150 }
151
152 thermal_error_t thermal_events_init(struct thermal_handler *th)
153 {
154         thermal_events_ops_init(&th->ops->events);
155
156         if (nl_thermal_connect(&th->sk_event, &th->cb_event))
157                 return THERMAL_ERROR;
158
159         if (nl_subscribe_thermal(th->sk_event, th->cb_event,
160                                  THERMAL_GENL_EVENT_GROUP_NAME))
161                 return THERMAL_ERROR;
162
163         return THERMAL_SUCCESS;
164 }