55#include <stdio.h>
66#include <stdlib.h>
77#include <unistd.h>
8+ #include <limits.h>
89
910#include <thermal.h>
1011#include "thermal_nl.h"
@@ -33,6 +34,11 @@ static struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = {
3334 [THERMAL_GENL_ATTR_CDEV_CUR_STATE ] = { .type = NLA_U32 },
3435 [THERMAL_GENL_ATTR_CDEV_MAX_STATE ] = { .type = NLA_U32 },
3536 [THERMAL_GENL_ATTR_CDEV_NAME ] = { .type = NLA_STRING },
37+
38+ /* Thresholds */
39+ [THERMAL_GENL_ATTR_THRESHOLD ] = { .type = NLA_NESTED },
40+ [THERMAL_GENL_ATTR_THRESHOLD_TEMP ] = { .type = NLA_U32 },
41+ [THERMAL_GENL_ATTR_THRESHOLD_DIRECTION ] = { .type = NLA_U32 },
3642};
3743
3844static int parse_tz_get (struct genl_info * info , struct thermal_zone * * tz )
@@ -182,6 +188,48 @@ static int parse_tz_get_gov(struct genl_info *info, struct thermal_zone *tz)
182188 return THERMAL_SUCCESS ;
183189}
184190
191+ static int parse_threshold_get (struct genl_info * info , struct thermal_zone * tz )
192+ {
193+ struct nlattr * attr ;
194+ struct thermal_threshold * __tt = NULL ;
195+ size_t size = 0 ;
196+ int rem ;
197+
198+ /*
199+ * The size contains the size of the array and we want to
200+ * access the last element, size - 1.
201+ *
202+ * The variable size is initialized to zero but it will be
203+ * then incremented by the first if() statement. The message
204+ * attributes are ordered, so the first if() statement will be
205+ * always called before the second one. If it happens that is
206+ * not the case, then it is a kernel bug.
207+ */
208+ nla_for_each_nested (attr , info -> attrs [THERMAL_GENL_ATTR_THRESHOLD ], rem ) {
209+
210+ if (nla_type (attr ) == THERMAL_GENL_ATTR_THRESHOLD_TEMP ) {
211+
212+ size ++ ;
213+
214+ __tt = realloc (__tt , sizeof (* __tt ) * (size + 2 ));
215+ if (!__tt )
216+ return THERMAL_ERROR ;
217+
218+ __tt [size - 1 ].temperature = nla_get_u32 (attr );
219+ }
220+
221+ if (nla_type (attr ) == THERMAL_GENL_ATTR_THRESHOLD_DIRECTION )
222+ __tt [size - 1 ].direction = nla_get_u32 (attr );
223+ }
224+
225+ if (__tt )
226+ __tt [size ].temperature = INT_MAX ;
227+
228+ tz -> thresholds = __tt ;
229+
230+ return THERMAL_SUCCESS ;
231+ }
232+
185233static int handle_netlink (struct nl_cache_ops * unused ,
186234 struct genl_cmd * cmd ,
187235 struct genl_info * info , void * arg )
@@ -210,6 +258,10 @@ static int handle_netlink(struct nl_cache_ops *unused,
210258 ret = parse_tz_get_gov (info , arg );
211259 break ;
212260
261+ case THERMAL_GENL_CMD_THRESHOLD_GET :
262+ ret = parse_threshold_get (info , arg );
263+ break ;
264+
213265 default :
214266 return THERMAL_ERROR ;
215267 }
@@ -253,6 +305,34 @@ static struct genl_cmd thermal_cmds[] = {
253305 .c_maxattr = THERMAL_GENL_ATTR_MAX ,
254306 .c_attr_policy = thermal_genl_policy ,
255307 },
308+ {
309+ .c_id = THERMAL_GENL_CMD_THRESHOLD_GET ,
310+ .c_name = (char * )"Get thresholds list" ,
311+ .c_msg_parser = handle_netlink ,
312+ .c_maxattr = THERMAL_GENL_ATTR_MAX ,
313+ .c_attr_policy = thermal_genl_policy ,
314+ },
315+ {
316+ .c_id = THERMAL_GENL_CMD_THRESHOLD_ADD ,
317+ .c_name = (char * )"Add a threshold" ,
318+ .c_msg_parser = handle_netlink ,
319+ .c_maxattr = THERMAL_GENL_ATTR_MAX ,
320+ .c_attr_policy = thermal_genl_policy ,
321+ },
322+ {
323+ .c_id = THERMAL_GENL_CMD_THRESHOLD_DELETE ,
324+ .c_name = (char * )"Delete a threshold" ,
325+ .c_msg_parser = handle_netlink ,
326+ .c_maxattr = THERMAL_GENL_ATTR_MAX ,
327+ .c_attr_policy = thermal_genl_policy ,
328+ },
329+ {
330+ .c_id = THERMAL_GENL_CMD_THRESHOLD_FLUSH ,
331+ .c_name = (char * )"Flush the thresholds" ,
332+ .c_msg_parser = handle_netlink ,
333+ .c_maxattr = THERMAL_GENL_ATTR_MAX ,
334+ .c_attr_policy = thermal_genl_policy ,
335+ },
256336};
257337
258338static struct genl_ops thermal_cmd_ops = {
@@ -263,13 +343,29 @@ static struct genl_ops thermal_cmd_ops = {
263343
264344struct cmd_param {
265345 int tz_id ;
346+ int temp ;
347+ int direction ;
266348};
267349
268350typedef int (* cmd_cb_t )(struct nl_msg * , struct cmd_param * );
269351
270352static int thermal_genl_tz_id_encode (struct nl_msg * msg , struct cmd_param * p )
271353{
272- if (p -> tz_id >= 0 && nla_put_u32 (msg , THERMAL_GENL_ATTR_TZ_ID , p -> tz_id ))
354+ if (nla_put_u32 (msg , THERMAL_GENL_ATTR_TZ_ID , p -> tz_id ))
355+ return -1 ;
356+
357+ return 0 ;
358+ }
359+
360+ static int thermal_genl_threshold_encode (struct nl_msg * msg , struct cmd_param * p )
361+ {
362+ if (thermal_genl_tz_id_encode (msg , p ))
363+ return -1 ;
364+
365+ if (nla_put_u32 (msg , THERMAL_GENL_ATTR_THRESHOLD_TEMP , p -> temp ))
366+ return -1 ;
367+
368+ if (nla_put_u32 (msg , THERMAL_GENL_ATTR_THRESHOLD_DIRECTION , p -> direction ))
273369 return -1 ;
274370
275371 return 0 ;
@@ -338,6 +434,46 @@ thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_
338434 THERMAL_GENL_CMD_TZ_GET_TEMP , 0 , tz );
339435}
340436
437+ thermal_error_t thermal_cmd_threshold_get (struct thermal_handler * th ,
438+ struct thermal_zone * tz )
439+ {
440+ struct cmd_param p = { .tz_id = tz -> id };
441+
442+ return thermal_genl_auto (th , thermal_genl_tz_id_encode , & p ,
443+ THERMAL_GENL_CMD_THRESHOLD_GET , 0 , tz );
444+ }
445+
446+ thermal_error_t thermal_cmd_threshold_add (struct thermal_handler * th ,
447+ struct thermal_zone * tz ,
448+ int temperature ,
449+ int direction )
450+ {
451+ struct cmd_param p = { .tz_id = tz -> id , .temp = temperature , .direction = direction };
452+
453+ return thermal_genl_auto (th , thermal_genl_threshold_encode , & p ,
454+ THERMAL_GENL_CMD_THRESHOLD_ADD , 0 , tz );
455+ }
456+
457+ thermal_error_t thermal_cmd_threshold_delete (struct thermal_handler * th ,
458+ struct thermal_zone * tz ,
459+ int temperature ,
460+ int direction )
461+ {
462+ struct cmd_param p = { .tz_id = tz -> id , .temp = temperature , .direction = direction };
463+
464+ return thermal_genl_auto (th , thermal_genl_threshold_encode , & p ,
465+ THERMAL_GENL_CMD_THRESHOLD_DELETE , 0 , tz );
466+ }
467+
468+ thermal_error_t thermal_cmd_threshold_flush (struct thermal_handler * th ,
469+ struct thermal_zone * tz )
470+ {
471+ struct cmd_param p = { .tz_id = tz -> id };
472+
473+ return thermal_genl_auto (th , thermal_genl_tz_id_encode , & p ,
474+ THERMAL_GENL_CMD_THRESHOLD_FLUSH , 0 , tz );
475+ }
476+
341477thermal_error_t thermal_cmd_exit (struct thermal_handler * th )
342478{
343479 if (genl_unregister_family (& thermal_cmd_ops ))
0 commit comments