5
5
#include <stdio.h>
6
6
#include <stdlib.h>
7
7
#include <unistd.h>
8
+ #include <limits.h>
8
9
9
10
#include <thermal.h>
10
11
#include "thermal_nl.h"
@@ -33,6 +34,11 @@ static struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = {
33
34
[THERMAL_GENL_ATTR_CDEV_CUR_STATE ] = { .type = NLA_U32 },
34
35
[THERMAL_GENL_ATTR_CDEV_MAX_STATE ] = { .type = NLA_U32 },
35
36
[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 },
36
42
};
37
43
38
44
static 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)
182
188
return THERMAL_SUCCESS ;
183
189
}
184
190
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
+
185
233
static int handle_netlink (struct nl_cache_ops * unused ,
186
234
struct genl_cmd * cmd ,
187
235
struct genl_info * info , void * arg )
@@ -210,6 +258,10 @@ static int handle_netlink(struct nl_cache_ops *unused,
210
258
ret = parse_tz_get_gov (info , arg );
211
259
break ;
212
260
261
+ case THERMAL_GENL_CMD_THRESHOLD_GET :
262
+ ret = parse_threshold_get (info , arg );
263
+ break ;
264
+
213
265
default :
214
266
return THERMAL_ERROR ;
215
267
}
@@ -253,6 +305,34 @@ static struct genl_cmd thermal_cmds[] = {
253
305
.c_maxattr = THERMAL_GENL_ATTR_MAX ,
254
306
.c_attr_policy = thermal_genl_policy ,
255
307
},
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
+ },
256
336
};
257
337
258
338
static struct genl_ops thermal_cmd_ops = {
@@ -263,13 +343,29 @@ static struct genl_ops thermal_cmd_ops = {
263
343
264
344
struct cmd_param {
265
345
int tz_id ;
346
+ int temp ;
347
+ int direction ;
266
348
};
267
349
268
350
typedef int (* cmd_cb_t )(struct nl_msg * , struct cmd_param * );
269
351
270
352
static int thermal_genl_tz_id_encode (struct nl_msg * msg , struct cmd_param * p )
271
353
{
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 ))
273
369
return -1 ;
274
370
275
371
return 0 ;
@@ -338,6 +434,46 @@ thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_
338
434
THERMAL_GENL_CMD_TZ_GET_TEMP , 0 , tz );
339
435
}
340
436
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
+
341
477
thermal_error_t thermal_cmd_exit (struct thermal_handler * th )
342
478
{
343
479
if (genl_unregister_family (& thermal_cmd_ops ))
0 commit comments