summaryrefslogtreecommitdiff
path: root/cleopatre/devkit/plcd/src/plcd_autoswitch.c
blob: 795eaa7087210e6aa229ced82a6789d27098c03e (plain)
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
/* SPC300 bundle {{{
 *
 * Copyright (C) 2013 Mstar Semiconductor
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    devkit/plcd/src/plcd_autoswitch.c
 * \brief   Handle autoswitch timer event.
 * \ingroup plcd
 *
 */
#include "plcd_autoswitch.h"

#include "libspid.h"

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <unistd.h>

/* "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);
}