4
This file implements part of the device thermal management policy
5
by providing the current thermal state for interested sw components.
7
Copyright (C) 2009-2010 Nokia Corporation
8
Copyright (C) 2013-2015 Jolla Oy.
10
@author Semi Malinen <semi.malinen@nokia.com>
11
@author Pekka Lundstrom <pekka.lundstrom@jollamobile.com>
12
@author Simo Piiroinen <simo.piiroinen@jollamobile.com>
14
This file is part of Dsme.
16
Dsme is free software; you can redistribute it and/or modify
17
it under the terms of the GNU Lesser General Public License
18
version 2.1 as published by the Free Software Foundation.
20
Dsme is distributed in the hope that it will be useful,
21
but WITHOUT ANY WARRANTY; without even the implied warranty of
22
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23
Lesser General Public License for more details.
25
You should have received a copy of the GNU Lesser General Public
26
License along with Dsme. If not, see <http://www.gnu.org/licenses/>.
30
* An example command line to obtain thermal state over D-Bus:
31
* $ dbus-send --system --print-reply --dest=com.nokia.thermalmanager /com/nokia/thermalmanager com.nokia.thermalmanager.get_thermal_state
33
* An example command line to obtain surface temperature estimate over D-Bus:
34
* $ dbus-send --system --print-reply --dest=com.nokia.thermalmanager /com/nokia/thermalmanager com.nokia.thermalmanager.estimate_surface_temperature
36
* An example command line to obtain core temperature over D-Bus:
37
* $ dbus-send --system --print-reply --dest=com.nokia.thermalmanager /com/nokia/thermalmanager com.nokia.thermalmanager.core_temperature
39
* An example command line to obtain battery temperature over D-Bus:
40
* $ dbus-send --system --print-reply --dest=com.nokia.thermalmanager /com/nokia/thermalmanager com.nokia.thermalmanager.battery_temperature
42
* An example command line to obtain named sensor temperature over D-Bus:
43
* $ dbus-send --system --print-reply --dest=com.nokia.thermalmanager /com/nokia/thermalmanager com.nokia.thermalmanager.sensor_temperature string:core
46
/* ========================================================================= *
49
* - maintains a set of registered thermal objects
50
* - polls status of each thermal object periodically
51
* - evaluates overall device thermal status
52
* - broadcasts thermal status changes within dsme and over D-Bus
53
* - handles thermal sensor related D-Bus queries
56
* - handles the actual sensor reading
57
* - defines the thermal limits and associated polling delays
58
* - hw specific sensors can be made available as plugins
61
* - acts as glue layer allowing communication between thermal
62
* manager and possibly hw specific sensor logic
64
* +-------------------------+
68
* +-------------------------+
73
* +-------------------------+
77
* |-----------------| VTAB |
81
* +-------------------------+
83
* The included-by-default generic thermal sensor plugin:
84
* - can read file based sensors (in /sys and /proc file systems)
85
* - allows enabling/disabling sensors on dsme startup/exit
86
* - allows configuring meta-sensors which take temperature
87
* value from some other sensor, apply optional offset and
88
* can define separate thermal limits for the resulting
89
* values (e.g. surface_temp = battery_temp - 3 etc).
91
* HW specific plugins can/must be added to deal with thermal
92
* sensors that can't be accessed via filesystem (e.g. old nokia
93
* devices where battery temperature is accessible via bme ipc only).
94
* The sensor update logic in thermal manager has been implemented
95
* to expect asynchronous sensor access to facilitate such indirect
98
* Simplified graph of sensor poll duty loop:
106
* thermal_manager_register_object
109
* thermal_manager_request_object_update <---------.
112
* thermal_object_request_update |
117
* Z (assumed: sensor access is async) Z iphb_timer
120
* thermal_object_handle_update |
123
* thermal_manager_handle_object_update |
126
* | thermal_manager_schedule_object_poll
128
* thermal_manager_broadcast_status
133
* UI_NOTIFICATION SHUTDOWN_POLICY
135
* More descriptive diagram can be generated from thermalmanager.dot.
137
* ========================================================================= */
141
#include "thermalmanager.h"
143
#include <iphbd/iphb_internal.h>
145
#include "dbusproxy.h"
146
#include "dsme_dbus.h"
148
#include "../include/dsme/modules.h"
149
#include "../include/dsme/modulebase.h"
150
#include "../include/dsme/logging.h"
151
#include "heartbeat.h"
153
#include <dsme/state.h>
154
#include <dsme/thermalmanager_dbus_if.h>
161
/* ========================================================================= *
162
* FORWARD_DECLARATIONS
163
* ========================================================================= */
165
/* ------------------------------------------------------------------------- *
167
* ------------------------------------------------------------------------- */
169
/** Prefix to use for all logging from this module */
170
#define PFIX "thermalmanager: "
172
/* ------------------------------------------------------------------------- *
174
* ------------------------------------------------------------------------- */
176
const char *thermal_status_name (THERMAL_STATUS status);
177
const char *thermal_status_repr (THERMAL_STATUS status);
179
/* ------------------------------------------------------------------------- *
181
* ------------------------------------------------------------------------- */
183
void thermal_manager_register_object (thermal_object_t *thermal_object);
184
void thermal_manager_unregister_object (thermal_object_t *thermal_object);
185
bool thermal_manager_object_is_registered (thermal_object_t *thermal_object);
186
static void thermal_manager_request_object_update (thermal_object_t *thermal_object);
187
void thermal_manager_handle_object_update (thermal_object_t *changed_object);
188
static void thermal_manager_schedule_object_poll (thermal_object_t *thermal_object);
190
bool thermal_manager_get_sensor_status (const char *sensor_name, THERMAL_STATUS *status, int *temperature);
191
bool thermal_manager_request_sensor_update (const char *sensor_name);
192
void thermal_manager_handle_sensor_update (const thermal_object_t *thermal_object);
193
static bool thermal_manager_have_pending_sensor_update (const char *sensor_name);
195
static void thermal_manager_broadcast_status (THERMAL_STATUS status, thermal_object_t *changed_object);
196
static void thermal_manager_broadcast_status_dsme (THERMAL_STATUS status, int temperature, const char *sensor_name);
197
static void thermal_manager_broadcast_status_dbus (THERMAL_STATUS status);
199
/* ------------------------------------------------------------------------- *
201
* ------------------------------------------------------------------------- */
203
static void thermal_manager_get_thermal_state_cb (const DsmeDbusMessage *request, DsmeDbusMessage **reply);
205
static void thermal_manager_handle_temperature_query (const DsmeDbusMessage *req, const char *sensor_name, DsmeDbusMessage **rsp);
206
static void thermal_manager_get_surface_temperature_cb (const DsmeDbusMessage *req, DsmeDbusMessage **rsp);
207
static void thermal_manager_get_core_temperature_cb (const DsmeDbusMessage *req, DsmeDbusMessage **rsp);
208
static void thermal_manager_get_battery_temperature_cb (const DsmeDbusMessage *req, DsmeDbusMessage **rsp);
209
static void thermal_manager_get_sensor_temperature_cb (const DsmeDbusMessage *req, DsmeDbusMessage **rsp);
211
/* ------------------------------------------------------------------------- *
213
* ------------------------------------------------------------------------- */
215
void module_init (module_t *handle);
216
void module_fini (void);
218
/* ========================================================================= *
220
* ========================================================================= */
222
/** DSME module handle for this module */
223
static module_t *this_module = 0;
225
/** List of registered thermal objects */
226
static GSList *thermal_objects = 0;
228
/** Currently accepted device thermal state */
229
static THERMAL_STATUS current_status = THERMAL_STATUS_NORMAL;
231
/** Flag for: D-Bus method handlers have been registered */
232
static bool dbus_methods_bound = false;
234
/* ========================================================================= *
236
* ========================================================================= */
238
/** Convert thermal status to name used in D-Bus signaling
240
* @param status thermal status
242
* @return string expected by dbus peers
245
thermal_status_name(THERMAL_STATUS status)
247
/* Note: Any deviation from strings defined in thermalmanager_dbus_if
248
* from libdsme constitutes a possible D-Bus API break and should
252
const char *res = "unknown";
255
case THERMAL_STATUS_LOW:
256
res = thermalmanager_thermal_status_low;
259
case THERMAL_STATUS_NORMAL:
260
res = thermalmanager_thermal_status_normal;
263
case THERMAL_STATUS_WARNING:
264
res = thermalmanager_thermal_status_warning;
267
case THERMAL_STATUS_ALERT:
268
res = thermalmanager_thermal_status_alert;
271
case THERMAL_STATUS_FATAL:
272
res = thermalmanager_thermal_status_fatal;
281
/** Convert thermal status to human readable string
283
* @param status thermal status
285
* @return name of the status
288
thermal_status_repr(THERMAL_STATUS status)
290
const char *repr = "UNKNOWN";
293
case THERMAL_STATUS_LOW: repr = "LOW"; break;
294
case THERMAL_STATUS_NORMAL: repr = "NORMAL"; break;
295
case THERMAL_STATUS_WARNING: repr = "WARNING"; break;
296
case THERMAL_STATUS_ALERT: repr = "ALERT"; break;
297
case THERMAL_STATUS_FATAL: repr = "FATAL"; break;
298
case THERMAL_STATUS_INVALID: repr = "INVALID"; break;
305
/* ========================================================================= *
307
* ========================================================================= */
309
/** Initiate thermal object state update
311
* Pass request to thermal sensor via thermal object abstraction layer.
313
* The temperature query is assumed to be asynchronous.
315
* Control returns to thermal manager when thermal object layer calls
316
* thermal_manager_handle_object_update() function.
318
* @param thermal_object registered thermal object
321
thermal_manager_request_object_update(thermal_object_t *thermal_object)
323
/* Ignore invalid / unregistered objects */
324
if( !thermal_manager_object_is_registered(thermal_object) )
327
/* Initiate fetching and evaluating of the current value */
328
thermal_object_request_update(thermal_object);
330
/* ... lower level activity ...
331
* -> thermal_object_handle_update()
332
* -> thermal_manager_handle_object_update()
333
* -> thermal_manager_schedule_object_poll()
340
/** Scedule iphb wakeup for updating thermal object
342
* Normally the required poll delay is decided at thermal sensor
343
* and depends on the current thermal state for the sensor.
345
* However, when status change is detected, several measurements
346
* are needed before the new status is accepted. For this purpose
347
* shorter polling delays are used while the status is in
348
* transitional state.
350
* Control returns to thermal manager when iphb wakeup message
351
* handler calls thermal_manager_request_object_update() function.
353
* @param thermal_object registered thermal object
356
thermal_manager_schedule_object_poll(thermal_object_t *thermal_object)
358
/* Ignore invalid / unregistered objects
360
if( !thermal_manager_object_is_registered(thermal_object) )
363
/* Schedule the next measurement point
365
DSM_MSGTYPE_WAIT msg = DSME_MSG_INIT(DSM_MSGTYPE_WAIT);
368
msg.data = thermal_object;
370
/* Start with fall back defaults */
371
int mintime = THERMAL_STATUS_POLL_DELAY_DEFAULT_MINIMUM;
372
int maxtime = THERMAL_STATUS_POLL_DELAY_DEFAULT_MAXIMUM;
374
if( thermal_object_status_in_transition(thermal_object) ) {
375
/* In transition: multiple measurements are neede to
376
* verify the status change - wake up more frequently */
377
mintime = THERMAL_STATUS_POLL_DELAY_TRANSITION_MINIMUM;
378
maxtime = THERMAL_STATUS_POLL_DELAY_TRANSITION_MAXIMUM;
380
/* and wake up from suspend to do the measurement */
381
msg.req.wakeup = true;
383
else if( !thermal_object_get_poll_delay(thermal_object,
384
&mintime, &maxtime) ) {
385
/* No wait period defined in the configuration - use
386
* shorter waits for abnormal states */
388
THERMAL_STATUS status = THERMAL_STATUS_INVALID;
389
int temperature = INVALID_TEMPERATURE;
391
thermal_object_get_sensor_status(thermal_object, &status,
395
case THERMAL_STATUS_ALERT:
396
case THERMAL_STATUS_FATAL:
397
mintime = THERMAL_STATUS_POLL_ALERT_TRANSITION_MINIMUM;
398
maxtime = THERMAL_STATUS_POLL_ALERT_TRANSITION_MAXIMUM;
406
if( mintime == maxtime ) {
407
dsme_log(LOG_DEBUG, PFIX"%s: check again in %d sec global slot",
408
thermal_object_get_name(thermal_object), mintime);
411
dsme_log(LOG_DEBUG, PFIX"%s: check again in %d to %d seconds",
412
thermal_object_get_name(thermal_object), mintime, maxtime);
415
msg.req.mintime = mintime;
416
msg.req.maxtime = maxtime;
418
/* Wakeup will be sent to "originating module". Since
419
* this function can end up being called from events
420
* dispatched at other modules, we need to maintain
421
* the context manually ... */
422
const module_t *from_module = current_module();
423
enter_module(this_module);
424
broadcast_internally(&msg);
425
enter_module(from_module);
427
/* ... wait for DSM_MSGTYPE_WAKEUP ...
428
* -> thermal_manager_request_object_update()
435
/** Register thermal object to thermal manager
437
* Add sensor object to the list of registered objects.
439
* Start update cycle:
440
* 1. query sensor temperature and status
441
* ... wait for sensor status
443
* 2. update device thermal state
444
* 3. broadcast device thermal state
446
* 4. schedule sensor specific iphb wakeup
447
* ... wait for iphb wakeup
451
* @param thermal_object unregistered thermal object
454
thermal_manager_register_object(thermal_object_t *thermal_object)
456
if( !thermal_object )
459
if( thermal_manager_object_is_registered(thermal_object) )
462
dsme_log(LOG_DEBUG, PFIX"%s: registered",
463
thermal_object_get_name(thermal_object));
465
// add the thermal object to the list of know thermal objects
466
thermal_objects = g_slist_append(thermal_objects, thermal_object);
468
thermal_manager_request_object_update(thermal_object);
474
/** Unregister thermal object from thermal manager
476
* Remove sensor object from the list of registered objects.
478
* It is expected that this function will be called only
479
* when dsme is on exit path and sensor backend plugins are
482
* Pending temperature requests are not canceled as it
483
* is assumed to be done by the thermal sensor plugin.
484
* If lower levels however do use thermal manager API
485
* to report changes later on, the calls are ignored
486
* because the objects are no longer registered.
488
* Similarly iphb wakeups relating to unregistered objects
489
* are ignored. And once thermal manager plugin is unloaded
490
* they will not be even dispatched anymore.
492
* @param thermal_object registered thermal object
495
thermal_manager_unregister_object(thermal_object_t *thermal_object)
497
if( !thermal_object )
500
if( !thermal_manager_object_is_registered(thermal_object) )
503
// remove the thermal object from the list of know thermal objects
504
thermal_objects = g_slist_remove(thermal_objects, thermal_object);
506
dsme_log(LOG_DEBUG, PFIX"%s: unregistered",
507
thermal_object_get_name(thermal_object));
513
/** Check if thermal object is registered to thermal manager
515
* @param thermal_object thermal object
517
* @return true if object is registerd, false otherwise
520
thermal_manager_object_is_registered(thermal_object_t *thermal_object)
522
bool is_registered = false;
524
if( !thermal_object )
527
if( g_slist_find(thermal_objects, thermal_object) )
528
is_registered = true;
531
return is_registered;
534
/** Get sensor status and temperature
536
* The status reported is the worst deviation from normal status found in
537
* the thermal objects that match the sensor_name given.
539
* For example, if there are sensors "core0", "core1", "core2" and "core3"
541
* Requesting "core0" status returns info from the "core0" as is.
543
* But requesting "core" status depends on overall status of all four
544
* matching sensors, which is highest state and temperature found, unless
545
* no sensors are in grave overheat state and at least one sensor is in
546
* low temperature states - in which case lowest state/temperature is
550
* - The status and temperature values are not modified if no matching
552
* - Values cached at thermal object level are used - the temperature
553
* is always the latest seen, but during lower level status transition
554
* the previous (stable) status is used
556
* @param sensor_name sensor name / sensor group name prefix
557
* @param status where to store sensor thermal status
558
* @param temperature where to store sensor temperature value
560
* @param return true if matching sensors were found and output values set;
564
thermal_manager_get_sensor_status(const char *sensor_name,
565
THERMAL_STATUS *status, int *temperature)
567
static volatile int recursing = 0;
571
/* In theory backend config parser should eliminate
572
* cyclic sensor dependencies - but if it still happens,
573
* it must not end up in infinite recursion ... */
574
if( ++recursing != 1 )
577
/* Initialize to invalid [lo,hi] range */
578
THERMAL_STATUS status_hi = THERMAL_STATUS_LOW;
579
THERMAL_STATUS status_lo = THERMAL_STATUS_FATAL;
580
int temp_lo = IGNORE_TEMP_ABOVE;
581
int temp_hi = IGNORE_TEMP_BELOW;
583
for( GSList *item = thermal_objects; item; item = item->next ) {
584
thermal_object_t *object = item->data;
586
if( !thermal_object_has_name_like(object, sensor_name) )
589
THERMAL_STATUS s = THERMAL_STATUS_INVALID;
590
int t = INVALID_TEMPERATURE;
592
if( !thermal_object_get_sensor_status(object, &s, &t) )
595
if( status_hi < s ) status_hi = s;
596
if( status_lo > s ) status_lo = s;
598
if( temp_hi < t ) temp_hi = t;
599
if( temp_lo > t ) temp_lo = t;
602
/* Skip if there were no matching sensors */
603
if( status_lo > status_hi || temp_lo > temp_hi )
606
/* Precedence: FATAL > ALERT > LOW > WARNING > NORMAL
608
* There is implicit exceptation that group of matching
609
* sensors share similar enough temperature config that
610
* this simplistic temperature selection makes sense.
613
if( status_lo < THERMAL_STATUS_NORMAL &&
614
status_hi < THERMAL_STATUS_ALERT ) {
616
*temperature = temp_lo;
620
*temperature = temp_hi;
632
/** Handle updated thermal object status
634
* Called by thermal object layer when
635
* a) fresh temperature & status data is available
636
* b) temperature query via thermal sensor failed
638
* The overall device thermal state is re-evaluated and
639
* changes broadcast both internally and externally.
641
* The next temperature poll time is scheduled.
643
* @param thermal_object registered thermal object
646
thermal_manager_handle_object_update(thermal_object_t *changed_object)
648
if( !thermal_manager_object_is_registered(changed_object) )
651
/* Scan all thermal objects for lowest/highest status */
652
THERMAL_STATUS highest_status = THERMAL_STATUS_NORMAL;
653
THERMAL_STATUS lowest_status = THERMAL_STATUS_NORMAL;
654
THERMAL_STATUS overall_status = THERMAL_STATUS_NORMAL;
656
for( GSList *item = thermal_objects; item; item = item->next ) {
657
thermal_object_t *object = item->data;
658
THERMAL_STATUS status = thermal_object_get_status(object);
660
/* Ignore sensors in invalid state */
661
if( status == THERMAL_STATUS_INVALID )
664
if( highest_status < status )
665
highest_status = status;
667
if( lowest_status > status )
668
lowest_status = status;
671
/* Decide overall status:
672
* If we have any ALERT of FATAL then that decides overall status
673
* During LOW, NORMAL or WARNING, any LOW wins
674
* Else status is the highest
676
if( lowest_status < THERMAL_STATUS_NORMAL &&
677
highest_status < THERMAL_STATUS_ALERT )
678
overall_status = lowest_status;
680
overall_status = highest_status;
682
/* Send notifications */
683
thermal_manager_broadcast_status(overall_status, changed_object);
685
/* Schedule the next inspection point */
686
thermal_manager_schedule_object_poll(changed_object);
692
/** Update current overall device thermal status
694
* Update bookkeeping and broadcast status both within dsme
697
* @param status device overall thermal status
698
* @param changed_object thermal object that caused status change
701
thermal_manager_broadcast_status(THERMAL_STATUS status,
702
thermal_object_t *changed_object)
704
/* Skip broadcast if no change */
705
if( current_status == status )
708
current_status = status;
710
/* First send an indication to D-Bus */
711
thermal_manager_broadcast_status_dbus(status);
713
/* Then broadcast an indication internally */
715
/* Note: The level gets attributed to the sensor that caused the
716
* change. Which is not wrong when elevating level, but can
717
* be completely bogus when returning to more normal state
718
* after having several sensors in elevated status.
720
* Since consumers of this if should not care what is the
721
* sensor that is reported, leaving this the way it has
725
int temperature = thermal_object_get_temperature(changed_object);
726
const char *sensor_name = thermal_object_get_name(changed_object);
728
thermal_manager_broadcast_status_dsme(status, temperature, sensor_name);
734
/** Broadcast overall device thermal status within dsme
736
* Map sensor thermal status to device status levels used by
737
* for example shutdown policy engine.
739
* Broadcast the changes via DSM_MSGTYPE_SET_THERMAL_STATUS event.
741
* @param status device overall thermal status
742
* @param temperature temperature to report
743
* @param sensor_name sensor to report as cause of the change
746
thermal_manager_broadcast_status_dsme(THERMAL_STATUS status,
748
const char *sensor_name)
750
static dsme_thermal_status_t prev = DSM_THERMAL_STATUS_NORMAL;
752
/* Map sensor status to device status */
753
dsme_thermal_status_t curr = DSM_THERMAL_STATUS_NORMAL;
756
case THERMAL_STATUS_LOW:
757
curr = DSM_THERMAL_STATUS_LOWTEMP;
761
case THERMAL_STATUS_INVALID:
762
case THERMAL_STATUS_NORMAL:
763
case THERMAL_STATUS_WARNING:
764
case THERMAL_STATUS_ALERT:
767
case THERMAL_STATUS_FATAL:
768
curr = DSM_THERMAL_STATUS_OVERHEATED;
772
/* Skip broadcast if no change */
778
/* Log state change */
780
case DSM_THERMAL_STATUS_LOWTEMP:
781
dsme_log(LOG_WARNING, PFIX"policy: low temperature (%s %dC)",
782
sensor_name, temperature);
786
case DSM_THERMAL_STATUS_NORMAL:
787
dsme_log(LOG_NOTICE, PFIX"policy: acceptable temperature (%s %dC)",
788
sensor_name, temperature);
791
case DSM_THERMAL_STATUS_OVERHEATED:
792
dsme_log(LOG_CRIT, PFIX"policy: overheated (%s %dC)", sensor_name,
797
/* Broadcast state change */
798
DSM_MSGTYPE_SET_THERMAL_STATUS msg =
799
DSME_MSG_INIT(DSM_MSGTYPE_SET_THERMAL_STATUS);
802
msg.temperature = temperature;
803
strncat(msg.sensor_name, sensor_name, sizeof msg.sensor_name - 1);
805
broadcast_internally(&msg);
811
/** Broadcast overall device thermal status via D-Bus
813
* Broadcast the changes as D-Bus signal
814
* com.nokia.thermalmanager.thermal_state_change_ind(state_name)
816
* @param status device overall thermal status
819
thermal_manager_broadcast_status_dbus(THERMAL_STATUS status)
821
static THERMAL_STATUS prev = THERMAL_STATUS_NORMAL;
828
const char *arg = thermal_status_name(status);
830
dsme_log(LOG_NOTICE, PFIX"send dbus signal %s.%s(%s)",
831
thermalmanager_interface,
832
thermalmanager_state_change_ind, arg);
834
DsmeDbusMessage *sig =
835
dsme_dbus_signal_new(thermalmanager_path,
836
thermalmanager_interface,
837
thermalmanager_state_change_ind);
839
dsme_dbus_message_append_string(sig, arg);
840
dsme_dbus_signal_emit(sig);
846
/** Request sensor status update
848
* All thermal objects have name matching the one given are
851
* For example, if there are sensors "core0", "core1", "core2" and "core3"
853
* Requesting "core0" update does "core0" only.
855
* But requesting "core" update does all four.
857
* @param sensor_name sensor name / sensor group name prefix
860
thermal_manager_request_sensor_update(const char *sensor_name)
863
for( GSList *item = thermal_objects; item; item = item->next ) {
864
thermal_object_t *object = item->data;
865
if( !thermal_object_has_name_like(object, sensor_name) )
867
thermal_object_request_update(object);
874
/** Check for pending sensor status request
876
* Check if any thermal objects with name matching the given on
877
* are still waiting for status update.
879
* For example, if there are sensors "core0", "core1", "core2" and "core3"
881
* Requesting "core0" checks "core0" only.
883
* But requesting "core" checks all four.
885
* @param sensor_name sensor name / sensor group name prefix
888
thermal_manager_have_pending_sensor_update(const char *sensor_name)
890
bool pending = false;
892
for( GSList *item = thermal_objects; item; item = item->next ) {
893
thermal_object_t *object = item->data;
895
/* Must be waiting for status */
896
if( !thermal_object_update_is_pending(object) )
899
/* And matching the name */
900
if( !thermal_object_has_name_like(object, sensor_name) )
903
/* But self-dependencies must not be allowed */
904
if( thermal_object_has_name(object, sensor_name) )
914
/** Update sensors that depend on the given thermal object
916
* If there are meta sensors that depend on temperature
917
* of the sensor that was updated, this function will
918
* re-evaluate the depending sensors.
920
* @param changed_object thermal object that just got updated
923
thermal_manager_handle_sensor_update(const thermal_object_t *changed_object)
925
const char *sensor_name = thermal_object_get_name(changed_object);
927
for( GSList *item = thermal_objects; item; item = item->next ) {
928
thermal_object_t *object = item->data;
930
/* Must be waiting for status */
931
if( !thermal_object_update_is_pending(object) )
934
/* and depending on the changed sensor */
935
const char *depends_on = thermal_object_get_depends_on(object);
939
if( !thermal_object_has_name_like(changed_object, depends_on) )
942
/* but self-dependency must not be allowed */
943
if( thermal_object_has_name(object, sensor_name) )
946
/* in case it is a group dependency, check all matching sensors */
947
if( thermal_manager_have_pending_sensor_update(depends_on) )
950
/* Initiate sensor re-evaluation at backend. When finished,
951
* a call to thermal_object_handle_update() is made.
953
if( !thermal_object_read_sensor(object) )
954
thermal_object_cancel_update(object);
956
// -> thermal_object_handle_update(object);
960
/* ========================================================================= *
962
* ========================================================================= */
964
/* Handle com.nokia.thermalmanager.get_thermal_state D-Bus method call
966
* @param req D-Bus method call message
967
* @param rsp Where to store D-Bus method return message
970
thermal_manager_get_thermal_state_cb(const DsmeDbusMessage *req,
971
DsmeDbusMessage **rsp)
973
*rsp = dsme_dbus_reply_new(req);
974
dsme_dbus_message_append_string(*rsp, thermal_status_name(current_status));
977
/** Helper for handling temperature query D-Bus method calls
979
* @param req D-Bus method call message
980
* @param sensor_name Sensor name / sensor group name prefix
981
* @param rsp Where to store D-Bus method return message
984
thermal_manager_handle_temperature_query(const DsmeDbusMessage *req,
985
const char *sensor_name,
986
DsmeDbusMessage **rsp)
988
THERMAL_STATUS status = THERMAL_STATUS_INVALID;
989
int temperature = INVALID_TEMPERATURE;
991
thermal_manager_get_sensor_status(sensor_name, &status, &temperature);
992
*rsp = dsme_dbus_reply_new(req);
993
dsme_dbus_message_append_int(*rsp, temperature);
996
/* Handle com.nokia.thermalmanager.estimate_surface_temperature method call
998
* Provides backwards compatibility with legacy D-Bus method
999
* that was originally implemented in Harmattan specific
1000
* sensor backend plugin.
1002
* @param req D-Bus method call message
1003
* @param rsp Where to store D-Bus method return message
1006
thermal_manager_get_surface_temperature_cb(const DsmeDbusMessage *req,
1007
DsmeDbusMessage **rsp)
1009
thermal_manager_handle_temperature_query(req, "surface", rsp);
1012
/* Handle com.nokia.thermalmanager.core_temperature D-Bus method call
1014
* Provides backwards compatibility with legacy D-Bus method
1015
* that was originally implemented in Harmattan specific
1016
* sensor backend plugin.
1018
* @param req D-Bus method call message
1019
* @param rsp Where to store D-Bus method return message
1022
thermal_manager_get_core_temperature_cb(const DsmeDbusMessage *req,
1023
DsmeDbusMessage **rsp)
1025
thermal_manager_handle_temperature_query(req, "core", rsp);
1028
/* Handle com.nokia.thermalmanager.battery_temperature D-Bus method call
1030
* Provides backwards compatibility with legacy D-Bus method
1031
* that was originally implemented in Harmattan specific
1032
* sensor backend plugin.
1034
* @param req D-Bus method call message
1035
* @param rsp Where to store D-Bus method return message
1038
thermal_manager_get_battery_temperature_cb(const DsmeDbusMessage *req,
1039
DsmeDbusMessage **rsp)
1041
thermal_manager_handle_temperature_query(req, "battery", rsp);
1044
/* Handle com.nokia.thermalmanager.sensor_temperature D-Bus method call
1046
* Provides backwards compatibility with legacy D-Bus method
1047
* that was originally implemented in Harmattan specific
1048
* sensor backend plugin.
1050
* @param req D-Bus method call message
1051
* @param rsp Where to store D-Bus method return message
1054
thermal_manager_get_sensor_temperature_cb(const DsmeDbusMessage *req,
1055
DsmeDbusMessage **rsp)
1057
const char *sensor = dsme_dbus_message_get_string(req);
1058
thermal_manager_handle_temperature_query(req, sensor, rsp);
1061
/** Array of D-Bus method calls supported by this plugin */
1062
static const dsme_dbus_binding_t dbus_methods_lut[] =
1064
{ thermal_manager_get_thermal_state_cb, thermalmanager_get_thermal_state },
1065
{ thermal_manager_get_surface_temperature_cb, thermalmanager_estimate_surface_temperature },
1066
{ thermal_manager_get_core_temperature_cb, thermalmanager_core_temperature },
1067
{ thermal_manager_get_battery_temperature_cb, thermalmanager_battery_temperature },
1068
{ thermal_manager_get_sensor_temperature_cb, thermalmanager_sensor_temperature },
1073
/* ========================================================================= *
1075
* ========================================================================= */
1077
/** Handler for iphb wakeup events
1079
DSME_HANDLER(DSM_MSGTYPE_WAKEUP, client, msg)
1081
thermal_object_t *thermal_object = msg->data;
1083
if( !thermal_manager_object_is_registered(thermal_object) )
1086
thermal_manager_request_object_update(thermal_object);
1092
/** Handler for connected to D-Bus system bus event
1094
DSME_HANDLER(DSM_MSGTYPE_DBUS_CONNECT, client, msg)
1096
dsme_log(LOG_DEBUG, PFIX"DBUS_CONNECT");
1098
/* Add dbus method call handlers */
1099
dsme_dbus_bind_methods(&dbus_methods_bound, dbus_methods_lut,
1100
thermalmanager_service, thermalmanager_interface);
1103
/** Handler for disconnected to D-Bus system bus event
1105
DSME_HANDLER(DSM_MSGTYPE_DBUS_DISCONNECT, client, msg)
1107
dsme_log(LOG_DEBUG, PFIX"DBUS_DISCONNECT");
1109
/* Remove dbus method call handlers */
1110
dsme_dbus_unbind_methods(&dbus_methods_bound, dbus_methods_lut,
1111
thermalmanager_service, thermalmanager_interface);
1114
/** Array of DSME event handlers implemented by this plugin */
1115
module_fn_info_t message_handlers[] =
1117
DSME_HANDLER_BINDING(DSM_MSGTYPE_WAKEUP),
1118
DSME_HANDLER_BINDING(DSM_MSGTYPE_DBUS_CONNECT),
1119
DSME_HANDLER_BINDING(DSM_MSGTYPE_DBUS_DISCONNECT),
1123
/* ========================================================================= *
1125
* ========================================================================= */
1127
/** Init hook that DSME plugins need to implement
1129
* @param handle DSME plugin handle
1132
module_init(module_t *handle)
1134
dsme_log(LOG_DEBUG, PFIX"loaded");
1136
this_module = handle;
1139
/** Exit hook that DSME plugins need to implement
1144
/* Clear remaining thermal objects from the registered list */
1145
if( thermal_objects ) {
1146
dsme_log(LOG_ERR, PFIX"registered thermal objects remain "
1150
thermal_manager_unregister_object(thermal_objects->data);
1151
while( thermal_objects );
1154
/* Remove dbus method call handlers */
1155
dsme_dbus_unbind_methods(&dbus_methods_bound, dbus_methods_lut,
1156
thermalmanager_service, thermalmanager_interface);
1158
dsme_log(LOG_DEBUG, PFIX"unloaded");