https://bitbucket.org/hudson/magic-lantern
Raw File
Tip revision: ddff68f3cebd33eb2132fb3fb6073e2be9a07221 authored by a1ex on 09 January 2014, 09:43:47 UTC
Close branch marekk17/raw_recc-60d-refresh-timer-1383690065386.
Tip revision: ddff68f
fio-5d3.c
#include "dryos.h"
#include "property.h"
#include "bmp.h"
#include "string.h"
#include "menu.h"
#include "config.h"

// File I/O wrappers for handling the dual card slot on 5D3

int ml_card_select = 2; // if autoexec.bin is on both cards, the one from SD is loaded
int card_select = 1;

#define SHOOTING_CARD_LETTER (card_select == 1 ? "A" : "B")
#define ML_CARD_LETTER (ml_card_select == 1 ? "A" : "B")

CONFIG_INT("card.test", card_test_enabled, 1);
CONFIG_INT("card.force_type", card_force_type, 0);

/* enable to slow down the write speed, which improves compatibility with certain cards */
/* only enable if needed */
CONFIG_INT("cf.workaround", cf_card_workaround, 0);

MENU_UPDATE_FUNC(card_info_display)
{
    //~ int pcmcia  = *(uint8_t*)0x68c88;
    //~ int ide     = *(uint8_t*)0x68c89;
    //~ int udma    = *(uint8_t*)0x68c8A;
    char* make  = (char*)0x68c8B;
    char* model = (char*)0x68cAA;
    int cf_present = is_dir("A:/");

    MENU_SET_VALUE("%s %s", cf_present ? make : "N/A", model);
    MENU_SET_ICON(cf_present ? MNI_ON : MNI_OFF, 0);
}

static void card_test(int type)
{
    // some cards have timing issues on 5D3
    // ML will test for this bug at startup, and refuse to run on cards that can cause trouble
    // http://www.magiclantern.fm/forum/index.php?topic=2528.0

    if (!cf_card_workaround)
    {
        /* save the config with workaround enabled now, because if the test fails, we may no longer able to save it */
        cf_card_workaround = 1;
        save_config(0,0);
        cf_card_workaround = 0;
    }

    if (is_dir(type ? "B:/" : "A:/"))
    {
        FILE* f = FIO_CreateFileEx(type ? "B:/test.dat" : "A:/test.dat");
        int fail = 0;
        for (int i = 0; i < 100; i++)
        {
            bmp_fill(COLOR_BLACK, 0, 0, 400, 38);
            char msg[50];
            snprintf(msg, sizeof(msg), "%s card test (%d%%)...", type ? "SD" : "CF", i+1);
            bmp_printf(FONT_CANON, 0, 0, msg);
            int r = FIO_WriteFile(f, (void*)YUV422_LV_BUFFER_1, 1025);
            if (r != 1025) { fail = 1; break; }
        }
        FIO_CloseFile(f);
        FIO_RemoveFile(type ? "B:/test.dat" : "A:/test.dat");
        bmp_fill(COLOR_BLACK, 0, 0, 400, 38);
        
        if (fail) // fsck!
        {
            int warning_enabling_workaround = (cf_card_workaround==0 && type==0);
            while(1)
            {
                bmp_fill(COLOR_BLACK, 0, 0, 550, 80);
                if (warning_enabling_workaround)
                {
                    bmp_printf(FONT_CANON, 0,  0, "CF test fail, enabling workaround.");
                    bmp_printf(FONT_CANON, 0, 40, "Restart the camera and try again.");
                    cf_card_workaround = 1;
                }
                else
                {
                    bmp_printf(FONT_CANON, 0, 0, type ? "SD card test failed!" : "CF card test failed!");
                    bmp_printf(FONT_CANON, 0, 40, "Do not use this card on 5D3!");
                }
                beep();
                info_led_blink(1, 1000, 1000);
            }
        }
    }
}

static int free_space_raw_a, free_space_raw_b;

void card_tests()
{
    if (card_test_enabled)
    {
        if (free_space_raw_a > 10) card_test(0);
        if (free_space_raw_b > 10) card_test(1);
        
        /* if it reaches this point, the cards are OK */
        card_test_enabled = 0;
    }
    
    /* on startup enforce selected card.
       if that card type is not available, canon will ignore this change */
    if (card_force_type)
    {
        uint32_t value = card_force_type;
        
        /* ensure valid property value (side effect safe) */
        if ((value == 1 && is_dir("A:/")) ||
            (value == 2 && is_dir("B:/")))
        {
            prop_request_change(PROP_CARD_SELECT, &value, 4);
        }
    }
}

static MENU_SELECT_FUNC(card_test_toggle)
{
    card_test_enabled = !card_test_enabled;
}

static MENU_UPDATE_FUNC(card_test_update)
{
    MENU_SET_VALUE(card_test_enabled ? "ON" : "OFF");
    MENU_SET_ICON(MNI_BOOL(card_test_enabled), 0);
    MENU_SET_ENABLED(card_test_enabled);
}


void find_ml_card()
{
    int ml_cf = is_dir("A:/ML");
    int ml_sd = is_dir("B:/ML");
    
    if (ml_cf && !ml_sd) ml_card_select = 1;
    else if (!ml_cf && ml_sd) ml_card_select = 2;
    else if (ml_cf && ml_sd)
    {
        clrscr();
        for (int i = 0; i < 5; i++)
        {
            bmp_printf(FONT_CANON, 0, 0, "ML is on both cards, format one of them!");
            msleep(1000);
            beep();
        }
        redraw_after(2000);
    }
    else
    {
        clrscr();
        for (int i = 0; i < 5; i++)
        {
            bmp_printf(FONT_CANON, 0, 0, "Could not find ML files.");
            msleep(1000);
            beep();
        }
        redraw_after(2000);
    }
    
    card_select = ml_card_select;
}

int cluster_size = 0;
static int cluster_size_a = 0;
static int cluster_size_b = 0;

int free_space_raw = 0;
static int free_space_raw_a = 0;
static int free_space_raw_b = 0;

int file_number = 0;
static int file_number_a = 0;
static int file_number_b = 0;

int folder_number = 0;
int folder_number_a = 0;
int folder_number_b = 0;

PROP_HANDLER(PROP_CARD_SELECT)
{
    card_select = buf[0];
    if (card_select == 1)
    {
        cluster_size = cluster_size_a;
        free_space_raw = free_space_raw_a;
        file_number = file_number_a;
        folder_number = folder_number_a;
    }
    else
    {
        cluster_size = cluster_size_b;
        free_space_raw = free_space_raw_b;
        file_number = file_number_b;
        folder_number = folder_number_b;
    }
}

PROP_HANDLER(PROP_CLUSTER_SIZE_A)
{
    cluster_size_a = buf[0];
    if (card_select == 1) cluster_size = buf[0];
}

PROP_HANDLER(PROP_CLUSTER_SIZE_B)
{
    cluster_size_b = buf[0];
    if (card_select == 2) cluster_size = buf[0];
}

PROP_HANDLER(PROP_FREE_SPACE_A)
{
    free_space_raw_a = buf[0];
    if (card_select == 1) free_space_raw = buf[0];
}

PROP_HANDLER(PROP_FREE_SPACE_B)
{
    free_space_raw_b = buf[0];
    if (card_select == 2) free_space_raw = buf[0];
}

PROP_HANDLER(PROP_FILE_NUMBER_A)
{
    file_number_a = buf[0];
    if (card_select == 1) file_number = buf[0];
}

PROP_HANDLER(PROP_FILE_NUMBER_B)
{
    file_number_b = buf[0];
    if (card_select == 2) file_number = buf[0];
}

PROP_HANDLER(PROP_FOLDER_NUMBER_A)
{
    folder_number_a = buf[0];
    if (card_select == 1) folder_number = buf[0];
}

PROP_HANDLER(PROP_FOLDER_NUMBER_B)
{
    folder_number_b = buf[0];
    if (card_select == 2) folder_number = buf[0];
}

static char dcim_dir_suffix[6];
static char dcim_dir[100];

PROP_HANDLER(PROP_DCIM_DIR_SUFFIX)
{
    snprintf(dcim_dir_suffix, sizeof(dcim_dir_suffix), (const char *)buf);
}

const char* get_dcim_dir()
{
    snprintf(dcim_dir, sizeof(dcim_dir), "%s:/DCIM/%03d%s", SHOOTING_CARD_LETTER, folder_number, dcim_dir_suffix);
    return dcim_dir;
}

static void guess_drive_letter(char* new_filename, const char* old_filename, int size)
{
    if (old_filename[1] == ':')
    {
        snprintf(new_filename, size, "%s", old_filename);
        return;
    }
    
    if ((old_filename[0] == 'M' && old_filename[1] == 'L' && old_filename[2] == '/') // something in ML dir
        || !strchr(old_filename, '/')) // something in root dir
    {
        snprintf(new_filename, 100, "%s:/%s", ML_CARD_LETTER, old_filename);
    }
    else
    {
        snprintf(new_filename, 100, "%s:/%s", SHOOTING_CARD_LETTER, old_filename);
    }
}

FILE* _FIO_Open(const char* filename, unsigned mode );
FILE* FIO_Open(const char* filename, unsigned mode )
{
    char new_filename[100];
    guess_drive_letter(new_filename, filename, 100);
    return _FIO_Open(new_filename, mode);
}

FILE* _FIO_CreateFile(const char* filename );
FILE* FIO_CreateFile(const char* filename )
{
    char new_filename[100];
    guess_drive_letter(new_filename, filename, 100);
    return _FIO_CreateFile(new_filename);
}

//~ int _FIO_GetFileSize(const char * filename, unsigned * size);
int FIO_GetFileSize(const char * filename, uint32_t * size)
{
    char new_filename[100];
    guess_drive_letter(new_filename, filename, 100);
    return _FIO_GetFileSize(new_filename, size);
}

int _FIO_RemoveFile(const char * filename);
int FIO_RemoveFile(const char * filename)
{
    char new_filename[100];
    guess_drive_letter(new_filename, filename, 100);
    return _FIO_RemoveFile(new_filename);
}

struct fio_dirent * _FIO_FindFirstEx(const char * dirname, struct fio_file * file);
struct fio_dirent * FIO_FindFirstEx(const char * dirname, struct fio_file * file)
{
    char new_dirname[100];
    guess_drive_letter(new_dirname, dirname, 100);
    return _FIO_FindFirstEx(new_dirname, file);
}

int _FIO_CreateDirectory(const char * dirname);
int FIO_CreateDirectory(const char * dirname)
{
    char new_dirname[100];
    guess_drive_letter(new_dirname, dirname, 100);
    return _FIO_CreateDirectory(new_dirname);
}

struct menu_entry card_menus[] = {
    {
        .name = "Card settings",
        .select = menu_open_submenu,
        .help = "Preferences related to SD/CF card operation.",
        .children =  (struct menu_entry[]) {
            /*
            {
                .name = "CF card", 
                .update = &card_info_display,
                .help = "CF card info: make and model."
            },*/
            {
                .name = "Card test at startup", 
                //~ .priv = &card_test_enabled, /* don't use priv, so it doesn't get displayed in the modified settings menu */
                .select = card_test_toggle,
                .update = card_test_update,
                .help = "File write test. Some cards may have compatibility issues.",
            },
            {
                .name = "CF card workaround",
                .priv = &cf_card_workaround,
                .max = 1,
                .help = "Slows down the CF write speed to let you use certain cards.",
                .help2 = "(e.g. Kingston 16GB 266x is known to require this)"
            },
            {
                .name = "Preferred card", 
                .priv = &card_force_type,
                .min = 0,
                .max = 2,
                .choices = CHOICES("OFF", "CF", "SD"),
                .help = "Make sure your preferred card is selected at startup."
            },
            MENU_EOL,
        }
    }
};

static void fio_init()
{
    menu_add( "Prefs", card_menus, COUNT(card_menus) );
}


INIT_FUNC("fio_init", fio_init);
back to top