/* SPC300 bundle {{{ * * Copyright (C) 2013 Mstar Semiconductor * * <<>> * * }}} */ /** * \file devkit/plcd/src/plcd_autoswitch.c * \brief Handle autoswitch timer event. * \ingroup plcd * */ #include "plcd_autoswitch.h" #include "libspid.h" #include #include #include #include #include /* "utest_override" include must be the last include. */ #include "utest_override.h" /* Autoswitch timer handler. */ timer_t autoswitch_timer; int autoswitch_en = 0; int autoswitch_timer_alive = 0; #define PLCD_CUR_IMG_PROC "/proc/spidimg/current_img_slot" #define PLCD_NEXT_IMG_PROC "/proc/spidimg/next_img_slot" #define PLCD_AUTOSWITCH_PROC "/proc/spidimg/autoswitch_en" static void plcd_autoswitch_handler (int signum) { FILE *cfp = NULL, *nfp = NULL; int slot = -1; int next_slot = -1; spidcom_image_desc_t img_desc; char mtd_name[12] = {0}; if (signum != SIGALRM) return; timer_delete (autoswitch_timer); if ((cfp = fopen (PLCD_CUR_IMG_PROC, "r")) != NULL) { if (fscanf (cfp, "%d", &slot) && slot != -1) { libspid_image_get_desc (LIBSPID_IMAGE_DESC_TYPE_ALTERNATE, &img_desc, mtd_name); sscanf (mtd_name, "/dev/mtd%d", &next_slot); next_slot -= 3; if (next_slot != slot) { if ((nfp = fopen (PLCD_NEXT_IMG_PROC, "w")) != NULL) { fprintf (nfp, "%d\n", next_slot); fclose (cfp); fclose (nfp); system ("reboot"); } } } fclose (cfp); } } void plcd_autoswitch_timer_init (void) { struct itimerspec its; FILE *fp = NULL; /* Check if autoswitch is enabled. */ if ((fp = fopen (PLCD_AUTOSWITCH_PROC, "r")) != NULL) { if ((fscanf (fp, "%d", &autoswitch_en) != 0) && (autoswitch_en == 1)) { /* Launch autoswitch timer. */ timer_create (CLOCK_REALTIME, NULL, &autoswitch_timer); its.it_value.tv_sec = PLCD_AUTOSWITCH_TIMEOUT_SEC; its.it_value.tv_nsec = 0; its.it_interval.tv_sec = 0; its.it_interval.tv_nsec = 0; timer_settime (autoswitch_timer, 0, &its, NULL); autoswitch_timer_alive = 1; signal (SIGALRM, plcd_autoswitch_handler); } fclose (fp); } } void plcd_autoswitch_image_update (void) { spidcom_image_desc_t img_desc[2]; char mtd_name[32] = {0}; if (libspid_image_get_desc (LIBSPID_IMAGE_DESC_TYPE_ALTERNATE, &img_desc[1], mtd_name) != LIBSPID_SUCCESS) { syslog (LOG_WARNING, "%s: unable to retrieve alternate image desc", __FUNCTION__); return; } if (libspid_image_get_desc (LIBSPID_IMAGE_DESC_TYPE_CURRENT, &img_desc[0], mtd_name) != LIBSPID_SUCCESS) { syslog (LOG_WARNING, "%s: unable to retrieve current image desc", __FUNCTION__); return; } /* First check if we really need to update the index: * - is it greater than the alternate * - is the alternate OK_ORIGIN * - is the alternate valid */ if ((img_desc[0].index > img_desc[1].index) || (img_desc[1].index == SPIDCOM_IMG_DESC_ORIGIN_INDEX) || !img_desc[1].is_valid) { syslog (LOG_INFO, "%s: current image index update not required for autoswitch", __FUNCTION__); return; } libspid_image_update_current_index (img_desc[1].index + 1, mtd_name); }