0001
0002
0003 #include <linux/netlink.h>
0004 #include <stdio.h>
0005 #include <stdlib.h>
0006 #include <unistd.h>
0007
0008
0009 #include <thermal.h>
0010 #include "thermal_nl.h"
0011
0012
0013
0014
0015
0016
0017
0018
0019 static int enabled_ops[__THERMAL_GENL_EVENT_MAX];
0020
0021 static int handle_thermal_event(struct nl_msg *n, void *arg)
0022 {
0023 struct nlmsghdr *nlh = nlmsg_hdr(n);
0024 struct genlmsghdr *genlhdr = genlmsg_hdr(nlh);
0025 struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
0026 struct thermal_handler_param *thp = arg;
0027 struct thermal_events_ops *ops = &thp->th->ops->events;
0028
0029 genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL);
0030
0031 arg = thp->arg;
0032
0033
0034
0035
0036 if (!enabled_ops[genlhdr->cmd])
0037 return THERMAL_SUCCESS;
0038
0039 switch (genlhdr->cmd) {
0040
0041 case THERMAL_GENL_EVENT_TZ_CREATE:
0042 return ops->tz_create(nla_get_string(attrs[THERMAL_GENL_ATTR_TZ_NAME]),
0043 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
0044
0045 case THERMAL_GENL_EVENT_TZ_DELETE:
0046 return ops->tz_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
0047
0048 case THERMAL_GENL_EVENT_TZ_ENABLE:
0049 return ops->tz_enable(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
0050
0051 case THERMAL_GENL_EVENT_TZ_DISABLE:
0052 return ops->tz_disable(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
0053
0054 case THERMAL_GENL_EVENT_TZ_TRIP_CHANGE:
0055 return ops->trip_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
0056 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
0057 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]),
0058 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]),
0059 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]), arg);
0060
0061 case THERMAL_GENL_EVENT_TZ_TRIP_ADD:
0062 return ops->trip_add(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
0063 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
0064 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]),
0065 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]),
0066 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]), arg);
0067
0068 case THERMAL_GENL_EVENT_TZ_TRIP_DELETE:
0069 return ops->trip_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
0070 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]), arg);
0071
0072 case THERMAL_GENL_EVENT_TZ_TRIP_UP:
0073 return ops->trip_high(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
0074 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
0075 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
0076
0077 case THERMAL_GENL_EVENT_TZ_TRIP_DOWN:
0078 return ops->trip_low(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
0079 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
0080 nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
0081
0082 case THERMAL_GENL_EVENT_CDEV_ADD:
0083 return ops->cdev_add(nla_get_string(attrs[THERMAL_GENL_ATTR_CDEV_NAME]),
0084 nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]),
0085 nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_MAX_STATE]), arg);
0086
0087 case THERMAL_GENL_EVENT_CDEV_DELETE:
0088 return ops->cdev_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]), arg);
0089
0090 case THERMAL_GENL_EVENT_CDEV_STATE_UPDATE:
0091 return ops->cdev_update(nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]),
0092 nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_CUR_STATE]), arg);
0093
0094 case THERMAL_GENL_EVENT_TZ_GOV_CHANGE:
0095 return ops->gov_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
0096 nla_get_string(attrs[THERMAL_GENL_ATTR_GOV_NAME]), arg);
0097 default:
0098 return -1;
0099 }
0100 }
0101
0102 static void thermal_events_ops_init(struct thermal_events_ops *ops)
0103 {
0104 enabled_ops[THERMAL_GENL_EVENT_TZ_CREATE] = !!ops->tz_create;
0105 enabled_ops[THERMAL_GENL_EVENT_TZ_DELETE] = !!ops->tz_delete;
0106 enabled_ops[THERMAL_GENL_EVENT_TZ_DISABLE] = !!ops->tz_disable;
0107 enabled_ops[THERMAL_GENL_EVENT_TZ_ENABLE] = !!ops->tz_enable;
0108 enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_UP] = !!ops->trip_high;
0109 enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DOWN] = !!ops->trip_low;
0110 enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_CHANGE] = !!ops->trip_change;
0111 enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_ADD] = !!ops->trip_add;
0112 enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DELETE] = !!ops->trip_delete;
0113 enabled_ops[THERMAL_GENL_EVENT_CDEV_ADD] = !!ops->cdev_add;
0114 enabled_ops[THERMAL_GENL_EVENT_CDEV_DELETE] = !!ops->cdev_delete;
0115 enabled_ops[THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = !!ops->cdev_update;
0116 enabled_ops[THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = !!ops->gov_change;
0117 }
0118
0119 thermal_error_t thermal_events_handle(struct thermal_handler *th, void *arg)
0120 {
0121 struct thermal_handler_param thp = { .th = th, .arg = arg };
0122
0123 if (!th)
0124 return THERMAL_ERROR;
0125
0126 if (nl_cb_set(th->cb_event, NL_CB_VALID, NL_CB_CUSTOM,
0127 handle_thermal_event, &thp))
0128 return THERMAL_ERROR;
0129
0130 return nl_recvmsgs(th->sk_event, th->cb_event);
0131 }
0132
0133 int thermal_events_fd(struct thermal_handler *th)
0134 {
0135 if (!th)
0136 return -1;
0137
0138 return nl_socket_get_fd(th->sk_event);
0139 }
0140
0141 thermal_error_t thermal_events_exit(struct thermal_handler *th)
0142 {
0143 if (nl_unsubscribe_thermal(th->sk_event, th->cb_event,
0144 THERMAL_GENL_EVENT_GROUP_NAME))
0145 return THERMAL_ERROR;
0146
0147 nl_thermal_disconnect(th->sk_event, th->cb_event);
0148
0149 return THERMAL_SUCCESS;
0150 }
0151
0152 thermal_error_t thermal_events_init(struct thermal_handler *th)
0153 {
0154 thermal_events_ops_init(&th->ops->events);
0155
0156 if (nl_thermal_connect(&th->sk_event, &th->cb_event))
0157 return THERMAL_ERROR;
0158
0159 if (nl_subscribe_thermal(th->sk_event, th->cb_event,
0160 THERMAL_GENL_EVENT_GROUP_NAME))
0161 return THERMAL_ERROR;
0162
0163 return THERMAL_SUCCESS;
0164 }