https://bitbucket.org/daniel_fort/magic-lantern
Raw File
Tip revision: a9b33dfb22fc935528e7ab7b97cd826ba0a03d5f authored by a1ex on 28 July 2014, 07:21:46 UTC
Close branch fio_create_return_0
Tip revision: a9b33df
gps.c
/** GPS Support */

#include "dryos.h"
#include "menu.h"
#include "config.h"
#include "property.h"
#include "gps.h"

#ifdef FEATURE_GPS_TWEAKS
static CONFIG_INT("gps.powersave", gps_powersave_tweak, 0);    /* this goes into menu */

//~ static volatile CONFIG_INT("gps.restore.value", gps_restore_value, 0);  /* internal GPS state, to be restored at next boot */
/*
 * Careful: gps_restore_value is shared by two tasks: Canon's property task and ML task that loads the config file.
 * Right now it may be ok, but it will cause trouble in the future config preset implementation if we are not careful.
 *
 * If gps_restore_value would be simply updated from prop handler, it will basically work, except for this scenario:
 * - props get initialized => gps_restore_value will be set
 * - config gets loaded => gps_restore_value will be overwritten
 * - if gps powersave tweak is enabled, all fine (that's what we want)
 * - if gps powersave tweak is disabled, we've got a subtle bug where gps_restore_value may no longer reflect Canon setting
 * 
 * With config presets, this would overwrite Canon setting with the config value every time a preset is changed.
 * 
 * CONFIG_INT_UPDATE may be helpful here, but needs further investigation.
 *
 * Another issue with using a config variable for gps_restore_value: if config auto-save is disabled,
 * remembering Canon setting will not work.
 *
 * Solution: do not use config files; use boolean config_flag_file_setting files
 * (that is, file present => re-enable the internal GPS at next boot.
 * 
 * This limits the workaround to the internal GPS only, but should solve the issues just described.
 */
#endif


#ifdef CONFIG_GPS
static PROP_INT(PROP_GPS, gps_state);

uint32_t gps_get_state()
{
    return gps_state;
}

static void gps_set(int new_state)
{
    //~ NotifyBox(2000, "gps_set(%d)", new_state);
    
    ASSERT(new_state == GPS_INTERNAL || new_state == GPS_EXTERNAL || new_state == GPS_OFF);   
    if ((int)gps_state != new_state)
    {
        prop_request_change(PROP_GPS, &new_state, 4);
    }
}

void gps_disable()
{
    gps_set(0);
}

void gps_enable(int type)
{
    gps_set(type);
}

#ifdef FEATURE_GPS_TWEAKS

/* if this file is present, we need to restore it at startup */
/* keep out of config file, to avoid interference between prop handlers and config engine,
 * and also to remove dependency on config autosave */
static char* get_gps_flag_file()
{
    static char file[0x80];
    snprintf(file, sizeof(file), "%srestore.gps", get_config_dir());
    return file;
}

void gps_tweaks_shutdown_hook()
{
    if (gps_powersave_tweak)
    {
        /* GPS internal? we should restore at next boot */
        /* any other value? do not restore */
        config_flag_file_setting_save(get_gps_flag_file(), gps_state == GPS_INTERNAL);

        /* internal GPS enabled? turn it off to save battery power */
        if (gps_state == GPS_INTERNAL)
        {
            gps_disable();
        }
    }
}

void gps_tweaks_startup_hook()
{
    if (gps_powersave_tweak)
    {
        /* should we restore the GPS? */
        int gps_restore_value = config_flag_file_setting_load(get_gps_flag_file());

        if (gps_restore_value)
        {
            /* re-enable the internal GPS (we have disabled it at shutdown) */
            gps_set(GPS_INTERNAL);
        }
    }
}

static MENU_UPDATE_FUNC(gps_powersave_tweak_update)
{
    if (!gps_powersave_tweak)
    {
        return;
    }
    
    switch (gps_state)
    {
        case GPS_OFF:
            MENU_SET_WARNING(MENU_WARN_NOT_WORKING, "GPS is turned off from Canon menu, nothing to do.");
            break;
        case GPS_EXTERNAL:
            MENU_SET_WARNING(MENU_WARN_NOT_WORKING, "GPS set to external; this feature is only for the internal one.");
            break;
        case GPS_INTERNAL:
            MENU_SET_WARNING(MENU_WARN_INFO,        "Internal GPS will be re-enabled at next startup.");
            break;
        default:
            MENU_SET_WARNING(MENU_WARN_NOT_WORKING, "GPS broken (unknown state 0x%x)", gps_state);
            break;
    }
}

static struct menu_entry gps_menus[] = {
    {
        .name   = "GPS Power Save",
        .priv   = &gps_powersave_tweak,
        .max    = 1,
        .update = gps_powersave_tweak_update,
        .help   = "Disable the internal GPS at power off to save power.",
    },
};

void gps_tweaks_init()
{
    menu_add( "Prefs", gps_menus, COUNT(gps_menus) );
}

INIT_FUNC(__FILE__, gps_tweaks_init);

#endif // FEATURE_GPS_TWEAKS

#endif // CONFIG_GPS
back to top