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

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

#include "libmme.h"
#include "libspid.h"
#include "plcd.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)
        && (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);
}