-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathctrlm_main.cpp
More file actions
6073 lines (5328 loc) · 250 KB
/
ctrlm_main.cpp
File metadata and controls
6073 lines (5328 loc) · 250 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* If not stated otherwise in this file or this component's license file the
* following copyright and licenses apply:
*
* Copyright 2015 RDK Management
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <sys/sysinfo.h>
#include <poll.h>
#include <glib.h>
#include <string.h>
#include <semaphore.h>
#include <dlfcn.h>
#include <memory>
#include <algorithm>
#include <fstream>
#include <secure_wrapper.h>
#include <rdkversion.h>
#include "jansson.h"
#include "libIBus.h"
#ifdef USE_DEPRECATED_IRMGR
#include "irMgr.h"
#include "plat_ir.h"
#endif
#include "sysMgr.h"
#ifdef BREAKPAD_SUPPORT
#include "client/linux/handler/exception_handler.h"
#endif
#include "comcastIrKeyCodes.h"
#include "ctrlm_version_build.h"
#include "ctrlm_hal_rf4ce.h"
#include "ctrlm_hal_ble.h"
#include "ctrlm_hal_ip.h"
#include "ctrlm.h"
#include "ctrlm_log.h"
#include "ctrlm_utils.h"
#include "ctrlm_database.h"
#include "ctrlm_rcu.h"
#include "ctrlm_validation.h"
#include "ctrlm_recovery.h"
#include "ctrlm_ir_controller.h"
#include "ctrlm_powermanager.h"
#ifdef CTRLM_THUNDER
#include "ctrlm_thunder_plugin_device_info.h"
#include "ctrlm_rcp_ipc_iarm_thunder.h"
#endif
#ifdef AUTH_ENABLED
#include "ctrlm_auth.h"
#include "ctrlm_hal_certificate.h"
#endif
#include "ctrlm_rfc.h"
#include "ctrlm_telemetry.h"
#include "ctrlm_config.h"
#include "ctrlm_config_default.h"
#include "ctrlm_tr181.h"
#include "rf4ce/ctrlm_rf4ce_network.h"
#include "ctrlm_device_update.h"
#include "ctrlm_vendor_network_factory.h"
#include "dsMgr.h"
#include "dsRpc.h"
#include "dsDisplay.h"
#ifdef SYSTEMD_NOTIFY
#include <systemd/sd-daemon.h>
#endif
#include <systemd/sd-bus.h>
#include "xr_voice_sdk.h"
#include "ctrlm_voice_obj.h"
#include "ctrlm_voice_obj_generic.h"
#include "ctrlm_voice_endpoint.h"
#include "ctrlm_irdb_interface.h"
#ifdef FDC_ENABLED
#include "xr_fdc.h"
#endif
#include<features.h>
#ifdef MEMORY_LOCK
#include "clnl.h"
#endif
using namespace std;
#ifndef CTRLM_VERSION
#define CTRLM_VERSION "1.0"
#endif
#define CTRLM_THREAD_NAME_MAIN "Ctrlm Main"
#define CTRLM_THREAD_NAME_DATABASE "Ctrlm Database"
#define CTRLM_THREAD_NAME_DEVICE_UPDATE "Ctrlm Device Update"
#define CTRLM_THREAD_NAME_VOICE_SDK "Voice SDK"
#define CTRLM_THREAD_NAME_IR_CONTROLLER "IR Controller"
#define CTRLM_THREAD_NAME_RF4CE "RF4CE"
#define CTRLM_THREAD_NAME_BLE "BLE"
#define CTRLM_DEFAULT_DEVICE_MAC_INTERFACE "eth0"
#define CTRLM_RESTART_DELAY_SHORT "0"
#define CTRLM_RESTART_UPDATE_TIMEOUT (5000)
#define CTRLM_RF4CE_LEN_IR_REMOTE_USAGE 14
#define CTRLM_RF4CE_LEN_LAST_KEY_INFO sizeof(ctrlm_last_key_info)
#define CTRLM_RF4CE_LEN_SHUTDOWN_TIME 4
#define CTRLM_RF4CE_LEN_PAIRING_METRICS sizeof(ctrlm_pairing_metrics_t)
#define CTRLM_MAIN_QUEUE_REPEAT_DELAY (5000)
#define NETWORK_ID_BASE_RF4CE 1
#define NETWORK_ID_BASE_IP 11
#define NETWORK_ID_BASE_BLE 21
#define NETWORK_ID_BASE_CUSTOM 41
#define CTRLM_MAIN_FIRST_BOOT_TIME_MAX (180) // maximum amount of uptime allowed (in seconds) for declaring "first boot"
typedef void (*ctrlm_queue_push_t)(gpointer);
typedef void (*ctrlm_monitor_poll)(void *data);
typedef struct {
const char * name;
ctrlm_queue_push_t queue_push;
ctrlm_obj_network_t * obj_network;
ctrlm_monitor_poll function;
ctrlm_thread_monitor_response_t response;
} ctrlm_thread_monitor_t;
typedef struct
{
bool has_ir_xr2;
bool has_ir_xr5;
bool has_ir_xr11;
bool has_ir_xr15;
bool has_ir_remote;
} ctrlm_ir_remote_usage;
typedef struct {
int controller_id;
ctrlm_key_source_t source_type;
guint32 source_key_code;
long long timestamp;
ctrlm_ir_remote_type last_ir_remote_type;
bool is_screen_bind_mode;
ctrlm_remote_keypad_config remote_keypad_config;
char source_name[CTRLM_RCU_RIB_ATTR_LEN_PRODUCT_NAME];
} ctrlm_last_key_info;
typedef struct {
gboolean active;
ctrlm_pairing_modes_t pairing_mode;
ctrlm_pairing_restrict_by_remote_t restrict_by_remote;
ctrlm_bind_status_t bind_status;
} ctrlm_pairing_window;
typedef struct {
unsigned long num_screenbind_failures;
unsigned long last_screenbind_error_timestamp;
ctrlm_bind_status_t last_screenbind_error_code;
char last_screenbind_remote_type[CTRLM_MAIN_SOURCE_NAME_MAX_LENGTH];
unsigned long num_non_screenbind_failures;
unsigned long last_non_screenbind_error_timestamp;
ctrlm_bind_status_t last_non_screenbind_error_code;
unsigned char last_non_screenbind_error_binding_type;
char last_non_screenbind_remote_type[CTRLM_MAIN_SOURCE_NAME_MAX_LENGTH];
} ctrlm_pairing_metrics_t;
static const char *key_source_names[sizeof(ctrlm_key_source_t)] =
{
"FP",
"IR",
"RF",
"INVALID"
};
typedef struct {
GThread * main_thread;
GMainLoop * main_loop;
sem_t semaphore;
sem_t ctrlm_utils_sem;
GAsyncQueue * queue;
string stb_name;
string device_id;
ctrlm_device_type_t device_type;
string service_account_id;
string partner_id;
string device_mac;
string experience;
string service_access_token;
time_t service_access_token_expiration;
guint service_access_token_expiration_tag;
sem_t service_access_token_semaphore;
string image_name;
string image_branch;
string image_version;
string image_build_time;
string db_path;
string minidump_path;
gboolean has_device_id;
gboolean has_device_type;
gboolean has_service_account_id;
gboolean has_partner_id;
gboolean has_experience;
gboolean has_service_access_token;
gboolean sat_enabled;
gboolean production_build;
bool rf4ce_enabled;
void * rf4ce_handle;
ctrlm_hal_rf4ce_main_t rf4ce_hal_main;
guint thread_monitor_timeout_val;
guint thread_monitor_timeout_tag;
guint thread_monitor_index;
bool thread_monitor_active;
bool thread_monitor_minidump;
string server_url_authservice;
guint authservice_poll_val;
guint authservice_poll_tag;
guint authservice_fast_poll_val;
guint authservice_fast_retries;
guint authservice_fast_retries_max;
guint bound_controller_qty;
gboolean recently_booted;
guint recently_booted_timeout_val;
guint recently_booted_timeout_tag;
gboolean line_of_sight;
guint line_of_sight_timeout_val;
guint line_of_sight_timeout_tag;
gboolean autobind;
guint autobind_timeout_val;
guint autobind_timeout_tag;
gboolean binding_button;
guint binding_button_timeout_val;
guint binding_button_timeout_tag;
gboolean binding_screen_active;
guint screen_bind_timeout_val;
guint screen_bind_timeout_tag;
gboolean one_touch_autobind_active;
guint one_touch_autobind_timeout_val;
guint one_touch_autobind_timeout_tag;
ctrlm_pairing_window pairing_window;
bool mask_pii;
guint crash_recovery_threshold;
gboolean successful_init;
ctrlm_ir_remote_usage ir_remote_usage_today;
ctrlm_ir_remote_usage ir_remote_usage_yesterday;
guint32 today;
ctrlm_pairing_metrics_t pairing_metrics;
char discovery_remote_type[CTRLM_HAL_RF4CE_USER_STRING_SIZE];
time_t shutdown_time;
ctrlm_last_key_info last_key_info;
gboolean loading_db;
map<ctrlm_controller_id_t, bool> precomission_table;
map<ctrlm_network_id_t, ctrlm_obj_network_t *> networks; // Map to hold the Networks that will be used by Control Manager
map<ctrlm_network_id_t, ctrlm_network_type_t> network_type; // Map to hold the Network types that will be used by Control Manager
vector<ctrlm_thread_monitor_t> monitor_threads;
int return_code;
ctrlm_voice_t *voice_session;
ctrlm_irdb_interface_t *irdb;
ctrlm_telemetry_t *telemetry;
ctrlm_cs_values_t cs_values;
#ifdef AUTH_ENABLED
ctrlm_auth_t *authservice;
ctrlm_hal_certificate_t *hal_certificate;
#endif
#ifdef CTRLM_THUNDER
Thunder::DeviceInfo::ctrlm_thunder_plugin_device_info_t *thunder_device_info;
#endif
ctrlm_powermanager_t *power_manager;
ctrlm_power_state_t power_state;
gboolean auto_ack;
gboolean local_conf;
guint telemetry_report_interval;
ctrlm_ir_controller_t *ir_controller;
#ifdef NETWORKED_STANDBY_MODE_ENABLED
gboolean wake_with_voice_allowed;
#endif
} ctrlm_global_t;
static ctrlm_global_t g_ctrlm;
// Prototypes
#ifdef AUTH_ENABLED
static gboolean ctrlm_has_authservice_data(void);
static gboolean ctrlm_load_authservice_data(void);
#ifdef AUTH_DEVICE_ID
static gboolean ctrlm_load_device_id(void);
static void ctrlm_main_has_device_id_set(gboolean has_id);
#endif
#ifdef AUTH_ACCOUNT_ID
static gboolean ctrlm_load_service_account_id(const char *account_id);
static void ctrlm_main_has_service_account_id_set(gboolean has_id);
#endif
#ifdef AUTH_PARTNER_ID
static gboolean ctrlm_load_partner_id(void);
static void ctrlm_main_has_partner_id_set(gboolean has_id);
#endif
#ifdef AUTH_EXPERIENCE
static gboolean ctrlm_load_experience(void);
static void ctrlm_main_has_experience_set(gboolean has_experience);
#endif
#ifdef AUTH_SAT_TOKEN
static gboolean ctrlm_load_service_access_token(void);
static void ctrlm_main_has_service_access_token_set(gboolean has_token);
#endif
#endif
static gboolean ctrlm_load_version(void);
static gboolean ctrlm_load_device_mac(void);
static gboolean ctrlm_load_device_type(void);
static void ctrlm_device_type_loaded(ctrlm_device_type_t device_type);
static void ctrlm_main_has_device_type_set(gboolean has_type);
#ifdef CTRLM_THUNDER
static void ctrlm_device_info_activated(void *user_data);
#endif
static void * ctrlm_load_hal_rf4ce(void);
static gboolean ctrlm_load_config(json_t **json_obj_root, json_t **json_obj_net_rf4ce, json_t **json_obj_voice, json_t **json_obj_device_update, json_t **json_obj_validation, json_t **json_obj_vsdk);
static gboolean ctrlm_iarm_init(void);
static void ctrlm_iarm_terminate(void);
static gboolean ctrlm_networks_pre_init(json_t *json_obj_net_rf4ce, json_t *json_obj_root);
static gboolean ctrlm_networks_init(void);
static void ctrlm_networks_terminate(void);
static void ctrlm_thread_monitor_init(void);
static void ctrlm_terminate(void);
static gboolean ctrlm_message_queue_delay(gpointer data);
static void ctrlm_trigger_startup_actions(void);
static gpointer ctrlm_main_thread(gpointer param);
static void ctrlm_queue_msg_destroy(gpointer msg);
static gboolean ctrlm_timeout_recently_booted(gpointer user_data);
static gboolean ctrlm_timeout_systemd_restart_delay(gpointer user_data);
static gboolean ctrlm_thread_monitor(gpointer user_data);
static gboolean ctrlm_was_cpu_halted(void);
static gboolean ctrlm_start_iarm(gpointer user_data);
#ifdef AUTH_ENABLED
static gboolean ctrlm_authservice_poll(gpointer user_data);
#ifdef AUTH_SAT_TOKEN
static gboolean ctrlm_authservice_expired(gpointer user_data);
#endif
#endif
static gboolean ctrlm_ntp_check(gpointer user_data);
static void ctrlm_signals_register(void);
static void ctrlm_signal_handler(int signal);
static void ctrlm_main_iarm_call_status_get_(ctrlm_main_iarm_call_status_t *status);
static void ctrlm_main_iarm_call_property_get_(ctrlm_main_iarm_call_property_t *property);
static void ctrlm_main_iarm_call_discovery_config_set_(ctrlm_main_iarm_call_discovery_config_t *config);
static void ctrlm_main_iarm_call_autobind_config_set_(ctrlm_main_iarm_call_autobind_config_t *config);
static void ctrlm_main_iarm_call_precommission_config_set_(ctrlm_main_iarm_call_precommision_config_t *config);
static void ctrlm_main_iarm_call_factory_reset_(ctrlm_main_iarm_call_factory_reset_t *reset);
static void ctrlm_main_iarm_call_controller_unbind_(ctrlm_main_iarm_call_controller_unbind_t *unbind);
static void ctrlm_main_update_export_controller_list(void);
static void ctrlm_main_iarm_call_ir_remote_usage_get_(ctrlm_main_iarm_call_ir_remote_usage_t *ir_remote_usage);
static void ctrlm_main_iarm_call_pairing_metrics_get_(ctrlm_main_iarm_call_pairing_metrics_t *pairing_metrics);
static void ctrlm_main_iarm_call_last_key_info_get_(ctrlm_main_iarm_call_last_key_info_t *last_key_info);
static void ctrlm_main_iarm_call_control_service_end_pairing_mode_(ctrlm_main_iarm_call_control_service_pairing_mode_t *pairing);
static void ctrlm_stop_one_touch_autobind_(ctrlm_network_id_t network_id);
static void ctrlm_close_pairing_window_(ctrlm_network_id_t network_id, ctrlm_close_pairing_window_reason reason);
static void ctrlm_pairing_window_bind_status_set_(ctrlm_bind_status_t bind_status);
static void ctrlm_discovery_remote_type_set_(const char* remote_type_str);
static void ctrlm_controller_product_name_get(ctrlm_controller_id_t controller_id, char *source_name) __attribute__((unused)); //USE_DEPRECATED_IRMGR
static void ctrlm_global_rfc_values_retrieved(const ctrlm_rfc_attr_t &attr);
static gboolean ctrlm_timeout_line_of_sight(gpointer user_data) __attribute__((unused)); //USE_DEPRECATED_IRMGR
static gboolean ctrlm_timeout_autobind(gpointer user_data) __attribute__((unused)); //USE_DEPRECATED_IRMGR
static gboolean ctrlm_timeout_binding_button(gpointer user_data);
static gboolean ctrlm_timeout_screen_bind(gpointer user_data);
static gboolean ctrlm_timeout_one_touch_autobind(gpointer user_data);
static gboolean ctrlm_main_handle_day_change_ir_remote_usage();
static void ctrlm_property_write_ir_remote_usage(void);
static guchar ctrlm_property_write_ir_remote_usage(guchar *data, guchar length);
static void ctrlm_property_read_ir_remote_usage(void);
static void ctrlm_property_write_pairing_metrics(void);
static guchar ctrlm_property_write_pairing_metrics(guchar *data, guchar length);
static void ctrlm_property_read_pairing_metrics(void);
static void ctrlm_property_write_last_key_info(void);
static guchar ctrlm_property_write_last_key_info(guchar *data, guchar length);
static void ctrlm_property_read_last_key_info(void);
static void ctrlm_property_write_shutdown_time(void);
static guchar ctrlm_property_write_shutdown_time(guchar *data, guchar length);
static void ctrlm_property_read_shutdown_time(void);
static void control_service_values_read_from_db();
#ifdef USE_DEPRECATED_IRMGR
static void ctrlm_check_for_key_tag(int key_tag) __attribute__((unused)); //USE_DEPRECATED_IRMGR
#endif
#ifdef MEMORY_LOCK
const char *memory_lock_progs[] = {
"/usr/bin/controlMgr",
"/usr/lib/libctrlm_hal_rf4ce.so.0.0.0",
"/usr/lib/libxraudio.so.0.0.0",
"/usr/lib/libxraudio-hal.so.0.0.0",
"/usr/lib/libxr_mq.so.0.0.0",
"/usr/lib/libxr-timer.so.0.0.0",
"/usr/lib/libxr-timestamp.so.0.0.0"
};
#endif
#if CTRLM_HAL_RF4CE_API_VERSION >= 9
static void ctrlm_crash_recovery_check();
static void ctrlm_backup_data();
#endif
static void ctrlm_ir_controller_thread_poll(void *data);
static void ctrlm_vsdk_thread_poll(void *data);
static void ctrlm_vsdk_thread_response(void *data);
#ifdef MEM_DEBUG
static gboolean ctrlm_memory_profile(gpointer user_data) {
g_mem_profile();
return(TRUE);
}
#endif
#ifdef BREAKPAD_SUPPORT
static bool ctrlm_minidump_callback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) {
XLOGD_FATAL("Minidump location: %s Status: %s", descriptor.path(), succeeded ? "SUCCEEDED" : "FAILED");
return succeeded;
}
#endif
gboolean ctrlm_is_production_build(void) {
return(g_ctrlm.production_build);
}
int main(int argc, char *argv[]) {
// Set stdout to be line buffered
setvbuf(stdout, NULL, _IOLBF, 0);
XLOGD_INFO("name <%-24s> version <%-7s> branch <%-20s> commit <%s>", "ctrlm-main", CTRLM_MAIN_VERSION, CTRLM_MAIN_BRANCH, CTRLM_MAIN_COMMIT_ID);
#ifdef MEMORY_LOCK
clnl_init();
for(unsigned int i = 0; i < (sizeof(memory_lock_progs) / sizeof(memory_lock_progs[0])); i++) {
if(ctrlm_file_exists(memory_lock_progs[i])) {
if(clnl_lock(memory_lock_progs[i], SECTION_TEXT)) {
XLOGD_ERROR("failed to lock instructions to memory <%s>", memory_lock_progs[i]);
} else {
XLOGD_INFO("successfully locked to memory <%s>", memory_lock_progs[i]);
}
} else {
XLOGD_DEBUG("file doesn't exist, cannot lock to memory <%s>", memory_lock_progs[i]);
}
}
#endif
ctrlm_signals_register();
#ifdef BREAKPAD_SUPPORT
std::string minidump_path = "/opt/minidumps";
#ifdef BREAKPAD_MINIDUMP_PATH_OVERRIDE
minidump_path = BREAKPAD_MINIDUMP_PATH_OVERRIDE;
#else
FILE *fp= NULL;;
if(( fp = fopen("/tmp/.SecureDumpEnable", "r")) != NULL) {
minidump_path = "/opt/secure/minidumps";
fclose(fp);
}
#endif
google_breakpad::MinidumpDescriptor descriptor(minidump_path.c_str());
google_breakpad::ExceptionHandler eh(descriptor, NULL, ctrlm_minidump_callback, NULL, true, -1);
//ctrlm_crash();
#endif
XLOGD_INFO("glib run-time version... %d.%d.%d", glib_major_version, glib_minor_version, glib_micro_version);
XLOGD_INFO("glib compile-time version... %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
const char *error = glib_check_version(GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
if(NULL != error) {
XLOGD_FATAL("Glib not compatible: %s", error);
return(-1);
} else {
XLOGD_INFO("Glib run-time library is compatible");
}
#ifdef MEM_DEBUG
XLOGD_WARN("Memory debug is ENABLED.");
g_mem_set_vtable(glib_mem_profiler_table);
#endif
sem_init(&g_ctrlm.ctrlm_utils_sem, 0, 1);
if(!ctrlm_iarm_init()) {
XLOGD_FATAL("Unable to initialize IARM bus.");
// TODO handle this failure such that it retries
return(-1);
}
vsdk_version_info_t version_info[VSDK_VERSION_QTY_MAX] = {0};
uint32_t qty_vsdk = VSDK_VERSION_QTY_MAX;
vsdk_version(version_info, &qty_vsdk);
for(uint32_t index = 0; index < qty_vsdk; index++) {
vsdk_version_info_t *entry = &version_info[index];
if(entry->name != NULL) {
XLOGD_INFO("name <%-24s> version <%-7s> branch <%-20s> commit <%s>", entry->name ? entry->name : "NULL", entry->version ? entry->version : "NULL", entry->branch ? entry->branch : "NULL", entry->commit_id ? entry->commit_id : "NULL");
}
}
vsdk_init();
//struct sched_param param;
//param.sched_priority = 10;
//if(0 != sched_setscheduler(0, SCHED_FIFO, ¶m)) {
// XLOGD_ERROR("Unable to set scheduler priority!");
//}
// Initialize control manager global structure
g_ctrlm.main_loop = g_main_loop_new(NULL, true);
g_ctrlm.main_thread = NULL;
g_ctrlm.queue = NULL;
g_ctrlm.production_build = true;
g_ctrlm.rf4ce_handle = ctrlm_load_hal_rf4ce();
g_ctrlm.rf4ce_enabled = (NULL == g_ctrlm.rf4ce_handle) ? false : true;
g_ctrlm.has_service_access_token = false;
g_ctrlm.sat_enabled = true;
g_ctrlm.service_access_token_expiration_tag = 0;
g_ctrlm.thread_monitor_timeout_val = JSON_INT_VALUE_CTRLM_GLOBAL_THREAD_MONITOR_PERIOD * 1000;
g_ctrlm.thread_monitor_index = 0;
g_ctrlm.thread_monitor_active = true;
g_ctrlm.thread_monitor_minidump = JSON_BOOL_VALUE_CTRLM_GLOBAL_THREAD_MONITOR_MINIDUMP;
g_ctrlm.server_url_authservice = JSON_STR_VALUE_CTRLM_GLOBAL_URL_AUTH_SERVICE;
g_ctrlm.authservice_poll_val = JSON_INT_VALUE_CTRLM_GLOBAL_AUTHSERVICE_POLL_PERIOD * 1000;
g_ctrlm.authservice_fast_poll_val = JSON_INT_VALUE_CTRLM_GLOBAL_AUTHSERVICE_FAST_POLL_PERIOD;
g_ctrlm.authservice_fast_retries = 0;
g_ctrlm.authservice_fast_retries_max = JSON_INT_VALUE_CTRLM_GLOBAL_AUTHSERVICE_FAST_MAX_RETRIES;
g_ctrlm.bound_controller_qty = 0;
g_ctrlm.recently_booted = FALSE;
g_ctrlm.recently_booted_timeout_val = JSON_INT_VALUE_CTRLM_GLOBAL_TIMEOUT_RECENTLY_BOOTED;
g_ctrlm.recently_booted_timeout_tag = 0;
g_ctrlm.line_of_sight = FALSE;
g_ctrlm.line_of_sight_timeout_val = JSON_INT_VALUE_CTRLM_GLOBAL_TIMEOUT_LINE_OF_SIGHT;
g_ctrlm.line_of_sight_timeout_tag = 0;
g_ctrlm.autobind = FALSE;
g_ctrlm.autobind_timeout_val = JSON_INT_VALUE_CTRLM_GLOBAL_TIMEOUT_AUTOBIND;
g_ctrlm.autobind_timeout_tag = 0;
g_ctrlm.binding_button = FALSE;
g_ctrlm.binding_button_timeout_val = JSON_INT_VALUE_CTRLM_GLOBAL_TIMEOUT_BUTTON_BINDING;
g_ctrlm.binding_button_timeout_tag = 0;
g_ctrlm.binding_screen_active = FALSE;
g_ctrlm.screen_bind_timeout_val = JSON_INT_VALUE_CTRLM_GLOBAL_TIMEOUT_SCREEN_BIND;
g_ctrlm.screen_bind_timeout_tag = 0;
g_ctrlm.one_touch_autobind_timeout_val = JSON_INT_VALUE_CTRLM_GLOBAL_TIMEOUT_ONE_TOUCH_AUTOBIND;
g_ctrlm.one_touch_autobind_timeout_tag = 0;
g_ctrlm.one_touch_autobind_active = FALSE;
g_ctrlm.pairing_window.active = FALSE;
g_ctrlm.pairing_window.bind_status = CTRLM_BIND_STATUS_NO_DISCOVERY_REQUEST;
g_ctrlm.pairing_window.restrict_by_remote = CTRLM_PAIRING_RESTRICT_NONE;
g_ctrlm.mask_pii = true;
g_ctrlm.db_path = JSON_STR_VALUE_CTRLM_GLOBAL_DB_PATH;
g_ctrlm.minidump_path = JSON_STR_VALUE_CTRLM_GLOBAL_MINIDUMP_PATH;
g_ctrlm.crash_recovery_threshold = JSON_INT_VALUE_CTRLM_GLOBAL_CRASH_RECOVERY_THRESHOLD;
g_ctrlm.successful_init = FALSE;
//g_ctrlm.precomission_table = g_hash_table_new(g_str_hash, g_str_equal);
g_ctrlm.loading_db = false;
g_ctrlm.return_code = 0;
g_ctrlm.power_manager = ctrlm_powermanager_t::get_instance();
g_ctrlm.power_state = ctrlm_main_get_system_power_state();
g_ctrlm.auto_ack = true;
g_ctrlm.local_conf = false;
g_ctrlm.telemetry = NULL;
g_ctrlm.telemetry_report_interval = JSON_INT_VALUE_CTRLM_GLOBAL_TELEMETRY_REPORT_INTERVAL;
g_ctrlm.service_access_token.clear();
g_ctrlm.has_device_id = false;
g_ctrlm.has_device_type = false;
g_ctrlm.has_service_account_id = false;
g_ctrlm.has_partner_id = false;
g_ctrlm.has_experience = false;
g_ctrlm.has_service_access_token = false;
sem_init(&g_ctrlm.service_access_token_semaphore, 0, 1);
g_ctrlm.last_key_info.last_ir_remote_type = CTRLM_IR_REMOTE_TYPE_UNKNOWN;
g_ctrlm.last_key_info.is_screen_bind_mode = false;
g_ctrlm.last_key_info.remote_keypad_config = CTRLM_REMOTE_KEYPAD_CONFIG_INVALID;
#ifdef NETWORKED_STANDBY_MODE_ENABLED
g_ctrlm.wake_with_voice_allowed = false;
#endif
errno_t safec_rc = strcpy_s(g_ctrlm.last_key_info.source_name, sizeof(g_ctrlm.last_key_info.source_name), ctrlm_rcu_ir_remote_types_str(g_ctrlm.last_key_info.last_ir_remote_type));
ERR_CHK(safec_rc);
g_ctrlm.discovery_remote_type[0] = '\0';
#ifdef MEM_DEBUG
g_mem_profile();
g_timeout_add_seconds(10, ctrlm_memory_profile, NULL);
#endif
XLOGD_INFO("load version");
if(!ctrlm_load_version()) {
XLOGD_FATAL("failed to load version");
return(-1);
}
// Launch a thread to handle DB writes asynchronously
// Create an asynchronous queue to receive incoming messages from the networks
g_ctrlm.queue = g_async_queue_new_full(ctrlm_queue_msg_destroy);
g_ctrlm.mask_pii = ctrlm_is_production_build() ? JSON_ARRAY_VAL_BOOL_CTRLM_GLOBAL_MASK_PII_0 : JSON_ARRAY_VAL_BOOL_CTRLM_GLOBAL_MASK_PII_1;
#ifdef TELEMETRY_SUPPORT
XLOGD_INFO("create Telemetry object");
g_ctrlm.telemetry = ctrlm_telemetry_t::get_instance();
#endif
XLOGD_INFO("create Voice object");
g_ctrlm.voice_session = new ctrlm_voice_generic_t();
XLOGD_INFO("ctrlm_rfc init");
// This tells the RFC component to go fetch all the enabled attributes once
// we are fully initialized. This brings us to parity with the current RFC/TR181
// implementation.
ctrlm_rfc_t *rfc = ctrlm_rfc_t::get_instance();
if(rfc) {
rfc->add_changed_listener(ctrlm_rfc_t::attrs::GLOBAL, &ctrlm_global_rfc_values_retrieved);
}
// TODO: We could possibly schedule this to run once every few hours or whatever
// the team decides is best.
// Check if recently booted
struct sysinfo s_info;
if(sysinfo(&s_info) != 0) {
XLOGD_ERROR("Unable to get system uptime");
} else {
XLOGD_INFO("System up for %lu seconds", s_info.uptime);
if(s_info.uptime < CTRLM_MAIN_FIRST_BOOT_TIME_MAX) { // System first boot
XLOGD_TELEMETRY("ctrlm_main: System first boot");
}
if(s_info.uptime < (long)(g_ctrlm.recently_booted_timeout_val / 1000)) { // System just booted
XLOGD_INFO("Setting recently booted to true");
g_ctrlm.recently_booted = TRUE;
}
}
XLOGD_INFO("load config");
// Load configuration from the filesystem
json_t *json_obj_root, *json_obj_net_rf4ce, *json_obj_voice, *json_obj_device_update, *json_obj_validation, *json_obj_vsdk;
json_obj_root = NULL;
json_obj_net_rf4ce = NULL;
json_obj_voice = NULL;
json_obj_device_update = NULL;
json_obj_validation = NULL;
json_obj_vsdk = NULL;
ctrlm_load_config(&json_obj_root, &json_obj_net_rf4ce, &json_obj_voice, &json_obj_device_update, &json_obj_validation, &json_obj_vsdk);
#ifdef TELEMETRY_SUPPORT
// set telemetry duration after config parsing
g_ctrlm.telemetry->set_duration(g_ctrlm.telemetry_report_interval);
#endif
XLOGD_INFO("load device mac");
if(!ctrlm_load_device_mac()) {
XLOGD_ERROR("failed to load device mac");
// Do not crash the program here
}
XLOGD_INFO("load device type");
if(!ctrlm_load_device_type()) {
XLOGD_ERROR("failed to load device type");
}
#ifdef AUTH_ENABLED
XLOGD_INFO("ctrlm_auth init");
g_ctrlm.authservice = ctrlm_auth_service_create(g_ctrlm.server_url_authservice);
g_ctrlm.hal_certificate = ctrlm_hal_certificate_get();
ctrlm_voice_cert_t device_cert;
bool ocsp_verify_stapling = false;
bool ocsp_verify_ca = false;
if(!g_ctrlm.hal_certificate->device_cert_get(device_cert, ocsp_verify_stapling, ocsp_verify_ca)) {
XLOGD_ERROR("unable to get device certificate");
} else {
if(!g_ctrlm.voice_session->voice_stb_data_device_certificate_set(device_cert, ocsp_verify_stapling, ocsp_verify_ca)) {
XLOGD_ERROR("unable to set device certificate");
}
}
if (!ctrlm_has_authservice_data()) {
if (!g_ctrlm.authservice->is_ready()) {
XLOGD_WARN("Authservice not ready, no reason to poll");
} else {
if (!ctrlm_load_authservice_data()) {
XLOGD_INFO("Starting polling authservice for device data");
g_ctrlm.authservice_poll_tag = ctrlm_timeout_create(g_ctrlm.recently_booted ? g_ctrlm.authservice_fast_poll_val : g_ctrlm.authservice_poll_val,
ctrlm_authservice_poll,
NULL);
if (!g_ctrlm.recently_booted) {
g_ctrlm.authservice_fast_retries = g_ctrlm.authservice_fast_retries_max;
}
}
}
}
#endif // AUTH_ENABLED
g_ctrlm.voice_session->voice_stb_data_stb_name_set(g_ctrlm.stb_name);
g_ctrlm.voice_session->voice_stb_data_pii_mask_set(g_ctrlm.mask_pii);
#if defined(BREAKPAD_SUPPORT) && !defined(BREAKPAD_MINIDUMP_PATH_OVERRIDE)
if(g_ctrlm.minidump_path != JSON_STR_VALUE_CTRLM_GLOBAL_MINIDUMP_PATH) {
google_breakpad::MinidumpDescriptor descriptor_json(g_ctrlm.minidump_path.c_str());
eh.set_minidump_descriptor(descriptor_json);
}
#endif
// Database init must occur after network qty and type are known
XLOGD_INFO("pre-init networks");
ctrlm_networks_pre_init(json_obj_net_rf4ce, json_obj_root);
XLOGD_INFO("init recovery");
ctrlm_recovery_init();
#if CTRLM_HAL_RF4CE_API_VERSION >= 9
// Check to see if we are recovering from a crash before init
ctrlm_crash_recovery_check();
#endif
XLOGD_INFO("init database");
if(!ctrlm_db_init(g_ctrlm.db_path.c_str())) {
#if CTRLM_HAL_RF4CE_API_VERSION >= 9
uint32_t invalid_db = 1;
ctrlm_recovery_property_set(CTRLM_RECOVERY_INVALID_CTRLM_DB, &invalid_db);
return(-1);
#endif
}
g_ctrlm.loading_db = true;
//Read shutdown time data from the db
ctrlm_property_read_shutdown_time();
//Read IR remote usage data from the db
ctrlm_property_read_ir_remote_usage();
//Read pairing metrics data from the db
ctrlm_property_read_pairing_metrics();
//Read last key info from the db
ctrlm_property_read_last_key_info();
g_ctrlm.loading_db = false;
// This needs to happen after the DB is init, but before voice
if(TRUE == g_ctrlm.recently_booted) {
g_ctrlm.recently_booted_timeout_tag = ctrlm_timeout_create(g_ctrlm.recently_booted_timeout_val - (s_info.uptime * 1000), ctrlm_timeout_recently_booted, NULL);
}
ctrlm_timeout_create(CTRLM_RESTART_UPDATE_TIMEOUT, ctrlm_timeout_systemd_restart_delay, NULL);
XLOGD_INFO("init validation");
ctrlm_validation_init(json_obj_validation);
XLOGD_INFO("init rcu");
ctrlm_rcu_init();
// Device update components needs to be initialized after controllers are loaded
XLOGD_INFO("init device update");
ctrlm_device_update_init(json_obj_device_update);
// Initialize semaphore
sem_init(&g_ctrlm.semaphore, 0, 0);
g_ctrlm.main_thread = g_thread_new("ctrlm_main", ctrlm_main_thread, NULL);
// Block until initialization is complete or a timeout occurs
XLOGD_INFO("Waiting for ctrlm main thread initialization...");
sem_wait(&g_ctrlm.semaphore);
XLOGD_INFO("init networks");
if(!ctrlm_networks_init()) {
XLOGD_FATAL("Unable to initialize networks");
return(-1);
}
XLOGD_INFO("init IR controller object");
g_ctrlm.ir_controller = ctrlm_ir_controller_t::get_instance();
g_ctrlm.ir_controller->mask_key_codes_set(g_ctrlm.mask_pii);
string ir_db_table;
ctrlm_db_ir_controller_create(ir_db_table);
g_ctrlm.ir_controller->db_table_set(ir_db_table);
g_ctrlm.ir_controller->db_load();
g_ctrlm.ir_controller->print_status();
ctrlm_rcp_ipc_iarm_thunder_t *rcp_ipc = ctrlm_rcp_ipc_iarm_thunder_t::get_instance();
if (rcp_ipc) {
rcp_ipc->register_ipc();
}
XLOGD_INFO("init voice");
g_ctrlm.voice_session->voice_configure_config_file_json(json_obj_voice, json_obj_vsdk, g_ctrlm.local_conf );
XLOGD_INFO("networks init complete");
#if CTRLM_HAL_RF4CE_API_VERSION >= 9
// Init was successful, create backups of all NVM files
ctrlm_backup_data();
// Terminate recovery component and reset all values
ctrlm_recovery_terminate(true);
#endif
if(json_obj_root) {
json_decref(json_obj_root);
}
//export device list for all devices on all networks for xconf update checks
XLOGD_INFO("init xconf device list");
ctrlm_main_update_export_controller_list();
// Thread monitor
ctrlm_thread_monitor_init();
g_ctrlm.successful_init = TRUE;
ctrlm_trigger_startup_actions();
XLOGD_INFO("Enter main loop");
g_main_loop_run(g_ctrlm.main_loop);
//Save the shutdown time if it is valid
time_t current_time = time(NULL);
if(g_ctrlm.shutdown_time < current_time) {
g_ctrlm.shutdown_time = current_time;
ctrlm_property_write_shutdown_time();
} else {
XLOGD_WARN("Current Time <%ld> is less than the last shutdown time <%ld>. Ignoring.", current_time, g_ctrlm.shutdown_time);
}
XLOGD_INFO("main loop exited");
ctrlm_terminate();
ctrlm_dsmgr_deinit();
if(g_ctrlm.voice_session != NULL) {
delete g_ctrlm.voice_session;
g_ctrlm.voice_session = NULL;
}
vsdk_term();
sem_destroy(&g_ctrlm.service_access_token_semaphore);
#if AUTH_ENABLED
if(g_ctrlm.authservice != NULL) {
delete g_ctrlm.authservice;
g_ctrlm.authservice = NULL;
}
#endif
sem_destroy(&g_ctrlm.ctrlm_utils_sem);
#ifdef MEMORY_LOCK
for(unsigned int i = 0; i < (sizeof(memory_lock_progs) / sizeof(memory_lock_progs[0])); i++) {
if(ctrlm_file_exists(memory_lock_progs[i])) {
clnl_unlock(memory_lock_progs[i], SECTION_TEXT);
}
}
clnl_destroy();
#endif
ctrlm_config_t::destroy_instance();
ctrlm_rfc_t::destroy_instance();
#ifdef TELEMETRY_SUPPORT
ctrlm_telemetry_t::destroy_instance();
#endif
ctrlm_ir_controller_t::destroy_instance();
ctrlm_powermanager_t::destroy_instance();
ctrlm_irdb_interface_t::destroy_instance();
if(g_ctrlm.rf4ce_handle != NULL) {
XLOGD_INFO("unload rf4ce hal");
dlclose(g_ctrlm.rf4ce_handle);
g_ctrlm.rf4ce_handle = NULL;
}
XLOGD_INFO("exit program");
return (g_ctrlm.return_code);
}
std::string ctrlm_main_ir_controller_name_get() {
return g_ctrlm.ir_controller->name_get();
}
void ctrlm_main_ir_last_keypress_get(ctrlm_ir_last_keypress_t *last_key_info) {
if (g_ctrlm.main_thread != g_thread_self ()) {
XLOGD_ERROR("not called from ctrlm_main_thread!!!!!");
if(!ctrlm_is_production_build()) {
g_assert(0);
}
} else {
last_key_info->last_key_time = g_ctrlm.ir_controller->last_key_time_get();
last_key_info->last_key_code = g_ctrlm.ir_controller->last_key_code_get();
}
}
void ctrlm_utils_sem_wait(){
sem_wait(&g_ctrlm.ctrlm_utils_sem);
}
void ctrlm_utils_sem_post(){
sem_post(&g_ctrlm.ctrlm_utils_sem);
}
void ctrlm_thread_monitor_init(void) {
ctrlm_thread_monitor_t thread_monitor;
g_ctrlm.thread_monitor_timeout_tag = ctrlm_timeout_create(g_ctrlm.thread_monitor_timeout_val, ctrlm_thread_monitor, NULL);
thread_monitor.name = CTRLM_THREAD_NAME_MAIN;
thread_monitor.queue_push = ctrlm_main_queue_msg_push;
thread_monitor.obj_network = NULL;
thread_monitor.function = NULL;
thread_monitor.response = CTRLM_THREAD_MONITOR_RESPONSE_ALIVE;
g_ctrlm.monitor_threads.push_back(thread_monitor);
thread_monitor.name = CTRLM_THREAD_NAME_DATABASE;
thread_monitor.queue_push = ctrlm_db_queue_msg_push_front;
thread_monitor.obj_network = NULL;
thread_monitor.function = NULL;
thread_monitor.response = CTRLM_THREAD_MONITOR_RESPONSE_ALIVE;
g_ctrlm.monitor_threads.push_back(thread_monitor);
thread_monitor.name = CTRLM_THREAD_NAME_DEVICE_UPDATE;
thread_monitor.queue_push = ctrlm_device_update_queue_msg_push;
thread_monitor.obj_network = NULL;
thread_monitor.function = NULL;
thread_monitor.response = CTRLM_THREAD_MONITOR_RESPONSE_ALIVE;
g_ctrlm.monitor_threads.push_back(thread_monitor);
thread_monitor.name = CTRLM_THREAD_NAME_VOICE_SDK;
thread_monitor.queue_push = NULL;
thread_monitor.obj_network = NULL;
thread_monitor.function = ctrlm_vsdk_thread_poll;
thread_monitor.response = CTRLM_THREAD_MONITOR_RESPONSE_ALIVE;
g_ctrlm.monitor_threads.push_back(thread_monitor);
thread_monitor.name = CTRLM_THREAD_NAME_IR_CONTROLLER;
thread_monitor.queue_push = NULL;
thread_monitor.obj_network = NULL;
thread_monitor.function = ctrlm_ir_controller_thread_poll;
thread_monitor.response = CTRLM_THREAD_MONITOR_RESPONSE_ALIVE;
g_ctrlm.monitor_threads.push_back(thread_monitor);
for(auto const &itr : g_ctrlm.networks) {
if(CTRLM_HAL_RESULT_SUCCESS == itr.second->init_result_) {
thread_monitor.name = itr.second->name_get();
thread_monitor.queue_push = NULL;
thread_monitor.obj_network = itr.second;
thread_monitor.function = NULL;
thread_monitor.response = CTRLM_THREAD_MONITOR_RESPONSE_ALIVE;
g_ctrlm.monitor_threads.push_back(thread_monitor);
}
}
g_ctrlm.monitor_threads.shrink_to_fit();
if(CTRLM_TR181_RESULT_SUCCESS != ctrlm_tr181_bool_get(CTRLM_RF4CE_TR181_THREAD_MONITOR_MINIDUMP_ENABLE, &g_ctrlm.thread_monitor_minidump)) {
XLOGD_INFO("Thread Monitor Minidump is <%s> (TR181 not present)", (g_ctrlm.thread_monitor_minidump ? "ENABLED" : "DISABLED"));
} else {
XLOGD_INFO("Thread Monitor Minidump is <%s>", (g_ctrlm.thread_monitor_minidump ? "ENABLED" : "DISABLED"));
}
// Run once to kick off the first poll
ctrlm_thread_monitor(NULL);
}
gboolean ctrlm_thread_monitor(gpointer user_data) {
if(g_ctrlm.thread_monitor_index < (60 * 60 * 1000)) { // One hour in milliseconds
XLOG_RAW("."); XLOG_FLUSH();
g_ctrlm.thread_monitor_index += g_ctrlm.thread_monitor_timeout_val;
} else {
XLOG_RAW("\n");
XLOGD_NO_LF(XLOG_LEVEL_INFO, "."); XLOG_FLUSH();
g_ctrlm.thread_monitor_index = 0;
}
#ifdef FDC_ENABLED
uint32_t limit_soft = 40;
uint32_t limit_hard = FD_SETSIZE - 20;
int32_t rc = xr_fdc_check(limit_soft, limit_hard, true);
if(rc < 0) {
XLOGD_ERROR("xr_fdc_check");
} else if(rc > 0) {
XLOGD_FATAL("xr_fdc_check hard limit");
ctrlm_quit_main_loop();
return(FALSE);
}
#endif
if(ctrlm_was_cpu_halted()) {
XLOGD_INFO("skipping response check due to power state <%s>",ctrlm_power_state_str(g_ctrlm.power_state));
g_ctrlm.thread_monitor_active = false; // Deactivate thread monitoring
} else if(!g_ctrlm.thread_monitor_active) {
XLOGD_INFO("activate due to power state <%s>",ctrlm_power_state_str(g_ctrlm.power_state));
g_ctrlm.thread_monitor_active = true; // Activate thread monitoring again
} else {