31 #include "iarmStatus.h"
32 #include "vrexLogInternal.h"
36 #include "libIBusDaemon.h"
37 #include "comcastIrKeyCodes.h"
39 #include "secure_wrapper.h"
54 #ifdef STANDALONE_TEST
55 #define ALIVE_CHECK_PERIOD_SEC 2
57 #define ALIVE_CHECK_PERIOD_SEC 60
60 #define ACCEPTABLE_FAILURES_BEFORE_HANG 3
62 #ifdef STANDALONE_TEST
63 #define APPLICATION_NAME "testStatus123\0"
65 #define APPLICATION_NAME "AppMSOTarget\0"
68 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
76 } iarm_status_thread_t;
86 static __iarm_key_map_t key_status_to_string_map[] = {
87 {
"KEYDOWN", KET_KEYDOWN},
89 {
"KEYREPEAT", KET_KEYREPEAT}
92 static __iarm_key_map_t key_to_string_map[] = {
93 {
"DIGIT0", KED_DIGIT0},
94 {
"DIGIT1", KED_DIGIT1},
95 {
"DIGIT2", KED_DIGIT2},
96 {
"DIGIT3", KED_DIGIT3},
97 {
"DIGIT4", KED_DIGIT4},
98 {
"DIGIT5", KED_DIGIT5},
99 {
"DIGIT6", KED_DIGIT6},
100 {
"DIGIT7", KED_DIGIT7},
101 {
"DIGIT8", KED_DIGIT8},
102 {
"DIGIT9", KED_DIGIT9},
103 {
"PERIOD", KED_PERIOD},
105 {
"DISCRETE_POWER_ON", KED_DISCRETE_POWER_ON},
106 {
"DISCRETE_POWER_STANDBY", KED_DISCRETE_POWER_STANDBY},
108 {
"SEARCH", KED_SEARCH},
109 {
"SETUP", KED_SETUP},
111 {
"RF_POWER", KED_RF_POWER},
112 {
"POWER", KED_POWER},
113 {
"FP_POWER", KED_FP_POWER},
114 {
"ARROWUP", KED_ARROWUP},
115 {
"ARROWDOWN", KED_ARROWDOWN},
116 {
"ARROWLEFT", KED_ARROWLEFT},
117 {
"ARROWRIGHT", KED_ARROWRIGHT},
118 {
"SELECT", KED_SELECT},
119 {
"ENTER", KED_ENTER},
121 {
"CHANNELUP", KED_CHANNELUP},
122 {
"CHANNELDOWN", KED_CHANNELDOWN},
123 {
"VOLUMEUP", KED_VOLUMEUP},
124 {
"VOLUMEDOWN", KED_VOLUMEDOWN},
126 {
"GUIDE", KED_GUIDE},
127 {
"VIEWINGGUIDE", KED_VIEWINGGUIDE},
129 {
"SETTINGS", KED_SETTINGS},
130 {
"PAGEUP", KED_PAGEUP},
131 {
"PAGEDOWN", KED_PAGEDOWN},
136 {
"KEY_RED_CIRCLE", KED_KEY_RED_CIRCLE},
137 {
"KEY_GREEN_DIAMOND", KED_KEY_GREEN_DIAMOND},
138 {
"KEY_BLUE_SQUARE", KED_KEY_BLUE_SQUARE},
139 {
"KEY_YELLOW_TRIANGLE", KED_KEY_YELLOW_TRIANGLE},
141 {
"FAVORITE", KED_FAVORITE},
142 {
"REWIND", KED_REWIND},
143 {
"FASTFORWARD", KED_FASTFORWARD},
146 {
"PAUSE", KED_PAUSE},
147 {
"RECORD", KED_RECORD},
148 {
"BYPASS", KED_BYPASS},
149 {
"TVVCR", KED_TVVCR},
151 {
"REPLAY", KED_REPLAY},
153 {
"RECALL_FAVORITE_0", KED_RECALL_FAVORITE_0},
154 {
"CLEAR", KED_CLEAR},
155 {
"DELETE", KED_DELETE},
156 {
"START", KED_START},
157 {
"POUND", KED_POUND},
158 {
"FRONTPANEL1", KED_FRONTPANEL1},
159 {
"FRONTPANEL2", KED_FRONTPANEL2},
163 {
"TVPOWER", KED_TVPOWER},
164 {
"PREVIOUS", KED_PREVIOUS},
167 {
"INPUTKEY", KED_INPUTKEY},
169 {
"MYDVR", KED_MYDVR},
170 {
"ONDEMAND", KED_ONDEMAND},
171 {
"STB_MENU", KED_STB_MENU},
172 {
"AUDIO", KED_AUDIO},
173 {
"FACTORY", KED_FACTORY},
174 {
"RFENABLE", KED_RFENABLE},
176 {
"UNDEFINEDKEY", KED_UNDEFINEDKEY},
180 {
"DISPLAY_SWAP", KED_DISPLAY_SWAP},
181 {
"PINP_MOVE", KED_PINP_MOVE},
182 {
"PINP_TOGGLE", KED_PINP_TOGGLE},
183 {
"PINP_CHDOWN", KED_PINP_CHDOWN},
184 {
"PINP_CHUP", KED_PINP_CHUP},
185 {
"DMC_ACTIVATE", KED_DMC_ACTIVATE},
186 {
"DMC_DEACTIVATE", KED_DMC_DEACTIVATE},
187 {
"DMC_QUERY", KED_DMC_QUERY},
188 {
"OTR_START", KED_OTR_START},
189 {
"OTR_STOP", KED_OTR_STOP}
192 static bool main_init =
false;
194 static iarm_status_thread_t main;
196 static bool in_power_save =
false;
197 static pthread_mutex_t power_save_mutex;
198 static pthread_mutex_t status_mutex;
201 static uint32_t __status_request_count;
202 static uint32_t __status_kill_count;
203 static unsigned char __battery_level_loaded[GP_MSO_BUS_API_MAX_BINDED_REMOTES-1];
208 static void *status_main(
void *arg);
210 static bool status_check_and_process(
void);
211 static IARM_Result_t process_status_msg(gpMSOBusAPI_Packet_t *getRequest);
212 static void status_handle_hang(
void);
214 static bool is_powered_on(
void);
220 IARM_Result_t IARMSTATUS_Start(
void)
222 IARM_Result_t rv = IARM_RESULT_INVALID_STATE;
223 if (
false == main_init) {
224 pthread_mutex_init (&power_save_mutex, NULL);
225 pthread_mutex_init (&status_mutex, NULL);
226 if (0 == pthread_create(&main.thread_id, NULL, status_main, NULL) ) {
227 main.initialized =
true;
232 rv = IARM_RESULT_SUCCESS;
235 in_power_save = !is_powered_on();
238 if (IARM_RESULT_SUCCESS != rv) {
246 IARM_Result_t IARMSTATUS_Stop(
void)
248 IARM_Result_t rv= IARM_RESULT_SUCCESS;
250 if (main.initialized) {
251 pthread_kill(main.thread_id, SIGTERM);
253 pthread_join(main.thread_id, NULL);
255 pthread_mutex_destroy (&power_save_mutex);
256 pthread_mutex_destroy (&status_mutex);
258 main.initialized =
false;
266 void IARMSTATUS_keyEventHandler(
const char *owner, IARM_EventId_t eventId,
void *data,
size_t len)
271 gpMSOBusAPI_UserCommand_t *key = (gpMSOBusAPI_UserCommand_t*)data;
273 for(i_status = ARRAY_SIZE(key_status_to_string_map) - 1; i_status >= 0; i_status--) {
274 if (key_status_to_string_map[i_status].value == key->keyStatus) {
279 for(i_key_value = ARRAY_SIZE(key_to_string_map) - 1; i_key_value >= 0; i_key_value--) {
280 if (key_to_string_map[i_key_value].value == key->commandCode) {
286 STATUS_LOG(
"remoteId <%u> received key %s:0x%08x -- %s:0x%08x\n",
288 (-1 == i_status?
"UNKNOWN":key_status_to_string_map[i_status].string),
290 (-1 == i_key_value?
"UNKNOWN":key_to_string_map[i_key_value].string),
298 uint32_t get_status_kill_count()
302 pthread_mutex_lock(&status_mutex);
303 kill_count = __status_kill_count;
304 pthread_mutex_unlock(&status_mutex);
312 unsigned char get_battery_level_loaded(
unsigned char remoteId)
314 unsigned char battery_level;
316 pthread_mutex_lock(&status_mutex);
317 battery_level = __battery_level_loaded[remoteId];
318 pthread_mutex_unlock(&status_mutex);
320 return battery_level;
326 static void *status_main(
void *arg)
330 STATUS_LOG(
"-- Start Status --\n");
335 STATUS_LOG(
" status heartbeat\n");
337 pthread_mutex_lock(&power_save_mutex);
338 if (
false == in_power_save) {
339 check = status_check_and_process();
341 if (
false == check) {
344 for (failed_count = 0; failed_count < ACCEPTABLE_FAILURES_BEFORE_HANG; failed_count++) {
345 check = status_check_and_process();
352 if (
false == check) {
354 status_handle_hang();
356 __status_request_count = 0;
360 pthread_mutex_unlock(&power_save_mutex);
362 sleep(ALIVE_CHECK_PERIOD_SEC);
371 static bool status_check_and_process(
void)
374 gpMSOBusAPI_Packet_t getRequest;
375 IARM_Result_t result;
376 bzero(&getRequest,
sizeof(gpMSOBusAPI_Packet_t));
377 getRequest.msgId = gpMSOBusAPI_MsgId_GetRfStatus;
378 getRequest.length =
sizeof(gpMSOBusAPI_RfStatus_t);
379 getRequest.index = 0;
382 STATUS_LOG(
" Requesting status\n");
384 result =
IARM_Bus_Call(IARM_BUS_GPMGR_NAME, IARM_BUS_GPMGR_API_MsgRequest, (
void *)&getRequest,
sizeof(gpMSOBusAPI_Packet_t));
386 if (IARM_RESULT_SUCCESS == result) {
387 result = process_status_msg(&getRequest);
390 if (IARM_RESULT_SUCCESS == result) {
400 static IARM_Result_t process_status_msg(gpMSOBusAPI_Packet_t *getRequest)
402 IARM_Result_t rv = IARM_RESULT_INVALID_STATE;
405 if ( (gpMSOBusAPI_MsgId_GetRfStatus == getRequest->msgId)
410 gpMSOBusAPI_RfStatus_t *rf = &getRequest->msg.RfStatus;
412 __status_request_count++;
414 rv = IARM_RESULT_SUCCESS;
416 if (1 == __status_request_count) {
417 STATUS_LOG(
"RfStatus: \n");
418 STATUS_LOG(
" versionInfo: version: major (%u)\n", rf->versionInfo.version.major);
419 STATUS_LOG(
" minor (%u)\n", rf->versionInfo.version.minor);
420 STATUS_LOG(
" revision (%u)\n", rf->versionInfo.version.revision);
421 STATUS_LOG(
" patch (%u)\n", rf->versionInfo.version.patch);
422 STATUS_LOG(
" : ctrl (%u)\n", rf->versionInfo.ctrl);
423 STATUS_LOG(
" : number (%u)\n", rf->versionInfo.number);
424 STATUS_LOG(
" : changeList (%u)\n", rf->versionInfo.changeList);
425 STATUS_LOG(
" macAddress %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", rf->macAddress[0],
433 STATUS_LOG(
" shortAddress (%u)\n", rf->shortAddress);
434 STATUS_LOG(
" panId (%u)\n", rf->panId);
435 STATUS_LOG(
" activeChannel: number (%u)\n", rf->activeChannel.Number);
436 STATUS_LOG(
" : pollution (%u)\n", rf->activeChannel.Pollution);
437 for (i = 0; i < 2; i++) {
438 gpMSOBusAPI_RfChannel_t *backupChannel = &rf->backupChannels[i];
439 STATUS_LOG(
" backupChannel[%u]: number (%u)\n", i, backupChannel->Number);
440 STATUS_LOG(
" : pollution (%u)\n", backupChannel->Pollution);
442 STATUS_LOG(
" lowUptime (%u)\n", rf->lowUptime);
443 STATUS_LOG(
" nbrBindRemotes (%u)\n", rf->nbrBindRemotes);
444 for (i = 0; i < GP_MSO_BUS_API_MAX_BINDED_REMOTES-1; i++) {
445 gpMSOBusAPI_BindRemote_t *boundRemote = &rf->bindRemotes[i];
447 if (0xFFFF != boundRemote->ShortAddress) {
448 STATUS_LOG(
" bindRemotes[%u]: macAddress %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
450 boundRemote->MacAddress[0],
451 boundRemote->MacAddress[1],
452 boundRemote->MacAddress[2],
453 boundRemote->MacAddress[3],
454 boundRemote->MacAddress[4],
455 boundRemote->MacAddress[5],
456 boundRemote->MacAddress[6],
457 boundRemote->MacAddress[7]);
458 STATUS_LOG(
" : shortAddress (%u)\n",
459 boundRemote->ShortAddress);
460 STATUS_LOG(
" : commandCount (%u)\n",
461 boundRemote->CommandCount);
462 STATUS_LOG(
" : lastCommand (%u)\n",
463 boundRemote->LastCommand);
464 STATUS_LOG(
" : timestampLastCommand (%u)\n",
465 boundRemote->TimestampLastCommand);
466 STATUS_LOG(
" : signalStrength (%u)\n",
467 boundRemote->SignalStrength);
468 STATUS_LOG(
" : linkQuality (%u)\n",
469 boundRemote->LinkQuality);
470 STATUS_LOG(
" : versionInfoSw (%X:%X:%X:%X)\n",
471 boundRemote->VersionInfoSw[0],
472 boundRemote->VersionInfoSw[1],
473 boundRemote->VersionInfoSw[2],
474 boundRemote->VersionInfoSw[3]);
475 STATUS_LOG(
" : versionInfoHw: manufacturer (%u)\n",
476 boundRemote->VersionInfoHw.manufacturer);
477 STATUS_LOG(
" : : model (%u)\n",
478 boundRemote->VersionInfoHw.model);
479 STATUS_LOG(
" : : hwRevision (%u)\n",
480 boundRemote->VersionInfoHw.hwRevision);
481 STATUS_LOG(
" : : lotCode (%u)\n",
482 boundRemote->VersionInfoHw.lotCode);
483 STATUS_LOG(
" : versionInfoIrdb (%X:%X:%X:%X)\n",
484 boundRemote->VersionInfoIrdb[0],
485 boundRemote->VersionInfoIrdb[1],
486 boundRemote->VersionInfoIrdb[2],
487 boundRemote->VersionInfoIrdb[3]);
488 STATUS_LOG(
" : batteryLevelLoaded (%u)\n",
489 boundRemote->BatteryLevelLoaded);
490 STATUS_LOG(
" : betterLevelUnloaded (%u)\n",
491 boundRemote->BatteryLevelUnloaded);
492 STATUS_LOG(
" : timestampeBatteryUpdate (%u)\n",
493 boundRemote->TimestampBatteryUpdate);
494 STATUS_LOG(
" : type[%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X]\n",
495 boundRemote->Type[0],
496 boundRemote->Type[1],
497 boundRemote->Type[2],
498 boundRemote->Type[3],
499 boundRemote->Type[4],
500 boundRemote->Type[5],
501 boundRemote->Type[6],
502 boundRemote->Type[7],
503 boundRemote->Type[8]);
504 STATUS_LOG(
" : controllerProperties (%u)\n",
505 boundRemote->ControllerProperties);
506 STATUS_LOG(
" : remoteId (%u)\n",
507 boundRemote->remoteId);
514 pthread_mutex_lock(&status_mutex);
515 for (i = 0; i < GP_MSO_BUS_API_MAX_BINDED_REMOTES-1; i++) {
516 gpMSOBusAPI_BindRemote_t *boundRemote = &rf->bindRemotes[i];
518 if (0xFFFF != boundRemote->ShortAddress) {
519 __battery_level_loaded[boundRemote->remoteId] = boundRemote->BatteryLevelLoaded;
522 pthread_mutex_unlock(&status_mutex);
524 STATUS_LOG(
"Status HeartBeat:\n");
526 for (i = 0; i < GP_MSO_BUS_API_MAX_BINDED_REMOTES-1; i++) {
527 gpMSOBusAPI_BindRemote_t *remote = &rf->bindRemotes[i];
529 STATUS_LOG(
"Active Channel(%u) LowUptime(%u) Successful Status Requests(%u) %.13s Kills (%u)\n",
530 rf->activeChannel, rf->lowUptime,
531 __status_request_count, APPLICATION_NAME, __status_kill_count);
534 if (0xFFFF != remote->ShortAddress) {
535 STATUS_LOG(
" RemoteID(%u) Model(%.9s) Controller Props(0x%08X) LQI(%u)\n",
536 remote->remoteId, remote->Type, remote->ControllerProperties, remote->LinkQuality);
541 STATUS_LOG(
"received unknown message response (%u) instead of status (%u)\n", getRequest->msgId, gpMSOBusAPI_MsgId_GetRfStatus);
547 static void status_increment_kill_count(
void)
549 pthread_mutex_lock(&status_mutex);
550 __status_kill_count++;
551 pthread_mutex_unlock(&status_mutex);
557 static void status_handle_hang(
void)
562 STATUS_LOG(
"HUNG iarmmgr detected. Killing NOW\n");
564 snprintf(command,
sizeof(command),
"killall %s", APPLICATION_NAME);
565 command[
sizeof(command)-1] =
'\0';
566 v_secure_system(command);
567 status_increment_kill_count();
570 static bool is_powered_on(
void)
573 param.
curState = IARM_BUS_PWRMGR_POWERSTATE_ON;
575 return (
bool) ((
IARM_Bus_Call(
IARM_BUS_PWRMGR_NAME,
"GetPowerState", (
void *)¶m,
sizeof(param)) == IARM_RESULT_SUCCESS) && (param.curState == IARM_BUS_PWRMGR_POWERSTATE_ON));
583 IARM_Bus_CommonAPI_PowerPreChange_Param_t *param = (IARM_Bus_CommonAPI_PowerPreChange_Param_t *) arg;
584 IARM_Result_t result = IARM_RESULT_SUCCESS;
587 STATUS_LOG(
"PowerPreChange state to %d (STANDBY %d ::ON %d)\n",
589 IARM_BUS_PWRMGR_POWERSTATE_STANDBY,
590 IARM_BUS_PWRMGR_POWERSTATE_ON);
592 pthread_mutex_lock(&power_save_mutex);
593 in_power_save = (param->newState != IARM_BUS_PWRMGR_POWERSTATE_ON);
594 pthread_mutex_unlock(&power_save_mutex);