//---------------------------------------------------------------------------

#include "ltrbootapi.h"
#include <stdlib.h>
#include <string.h>
#include "ltrd_protocol_defs.h"

#define LTRBOOTAPI_TIMEOUT  2000

#ifdef _WIN32
    int ___CPPdebugHook = 0;
#endif

static const TLTR_ERROR_STRING_DEF ErrorStrings[] =
{
    { LTRBOOT_ERROR_GET_ARRAY,          "Ошибка выполнения команды GET_ARRAY." },
    { LTRBOOT_ERROR_PUT_ARRAY,          "Ошибка выполнения команды PUT_ARRAY." },
    { LTRBOOT_ERROR_CALL_APPL,          "Ошибка выполнения команды CALL_APPLICATION." },
    { LTRBOOT_ERROR_GET_DESCRIPTION,    "Ошибка выполнения команды GET_DESCRIPTION." },
    { LTRBOOT_ERROR_PUT_DESCRIPTION,    "Ошибка выполнения команды PUT_DESCRIPTION." }
};

//-----------------------------------------------------------------------------
LTRBOOTAPI_DllExport(INT) LTRBOOT_Init(TLTR010 *module)
{
    return LTR010_Init(module);
}
//-----------------------------------------------------------------------------
LTRBOOTAPI_DllExport(INT) LTRBOOT_Open(TLTR010 *module, DWORD saddr, WORD sport, const CHAR *csn)
{
    return LTR010_Open(module, saddr, sport, csn);
}
//-----------------------------------------------------------------------------
LTRBOOTAPI_DllExport(INT) LTRBOOT_Close(TLTR010 *module)
{
    return LTR010_Close(module);
}
//-----------------------------------------------------------------------------
//                функции программирования модуля
//-----------------------------------------------------------------------------
LTRBOOTAPI_DllExport(INT) LTRBOOT_GetArray(TLTR010 *module, BYTE *buf, DWORD size, DWORD address)
{
    INT res = module == NULL ? LTR_ERROR_INVALID_MODULE_DESCR : buf==NULL ? LTR_ERROR_PARAMETERS : LTR_OK;


    if (res==LTR_OK)
    {
        DWORD sbuf[] =
        {
            CONTROL_COMMAND_START, CONTROL_COMMAND_BOOT_LOADER_GET_ARRAY, 0,0
        };
        sbuf[2] = address;
        sbuf[3] = size;

        res = LTR__GenericCtlFunc(&module->ltr,
                               sbuf, sizeof(sbuf), buf, size,
                               LTRBOOT_ERROR_GET_ARRAY, LTRBOOTAPI_TIMEOUT);
    }
    return res;
}
//-----------------------------------------------------------------------------
LTRBOOTAPI_DllExport(INT) LTRBOOT_PutArray(TLTR010 *module, const BYTE *buf, DWORD size, DWORD address)
{
    INT res = module == NULL ? LTR_ERROR_INVALID_MODULE_DESCR : buf==NULL ? LTR_ERROR_PARAMETERS : LTR_OK;
    if (res==LTR_OK)
    {
        size_t send_size = 4 * sizeof(DWORD) + size;
        LPBYTE pbuf = malloc(send_size);
        LPDWORD header = (LPDWORD)pbuf;

        if (pbuf!=NULL)
            res = LTR_ERROR_MEMORY_ALLOC;

        if (res==LTR_OK)
        {
            header[0] = CONTROL_COMMAND_START;
            header[1] = CONTROL_COMMAND_BOOT_LOADER_PUT_ARRAY;
            header[2] = address;
            header[3] = size;
            memcpy(&header[4], buf, size);
            res = LTR__GenericCtlFunc(&module->ltr,
                                  pbuf, (DWORD)send_size, NULL, 0,
                                  LTRBOOT_ERROR_PUT_ARRAY, LTRBOOTAPI_TIMEOUT);
        }
        free(pbuf);
    }
    return res;
}

//-----------------------------------------------------------------------------
LTRBOOTAPI_DllExport(INT) LTRBOOT_GetDescription(TLTR010 *module, TDESCRIPTION_LTR010 *description)
{
    INT res = module == NULL ? LTR_ERROR_INVALID_MODULE_DESCR : description==NULL ? LTR_ERROR_PARAMETERS : LTR_OK;
    if (res==LTR_OK)
    {
        DWORD sbuf[] =
        {
            CONTROL_COMMAND_START, CONTROL_COMMAND_BOOT_LOADER_GET_DESCRIPTION
        };

        res = LTR__GenericCtlFunc(&module->ltr,
                               sbuf, sizeof(sbuf), description, sizeof(TDESCRIPTION_LTR010),
                               LTRBOOT_ERROR_GET_DESCRIPTION, LTRBOOTAPI_TIMEOUT);
    }
    return res;
}


//-----------------------------------------------------------------------------
LTRBOOTAPI_DllExport(INT) LTRBOOT_SetDescription(TLTR010 *module, const TDESCRIPTION_LTR010 *description)
{

    INT res = module == NULL ? LTR_ERROR_INVALID_MODULE_DESCR : description==NULL ? LTR_ERROR_PARAMETERS : LTR_OK;
    if (res==LTR_OK)
    {
        BYTE pbuf[2 * sizeof(DWORD) + sizeof(TDESCRIPTION_LTR010)];
        LPDWORD header = (LPDWORD)pbuf;
        header[0] = CONTROL_COMMAND_START;
        header[1] = CONTROL_COMMAND_BOOT_LOADER_SET_DESCRIPTION;
        memcpy(&header[2], description, sizeof(TDESCRIPTION_LTR010));
        res = LTR__GenericCtlFunc(&module->ltr,
                                  pbuf, sizeof(pbuf), NULL, 0,
                                LTRBOOT_ERROR_PUT_DESCRIPTION, LTRBOOTAPI_TIMEOUT);
    }
    return res;
}

//-----------------------------------------------------------------------------
LTRBOOTAPI_DllExport(INT) LTRBOOT_CallApplication(TLTR010 *module, DWORD address)
{
    INT res = module == NULL ? LTR_ERROR_INVALID_MODULE_DESCR : LTR_OK;
    if (res==LTR_OK)
    {
        DWORD sbuf[] =
        {
            CONTROL_COMMAND_START, CONTROL_COMMAND_CALL_APPLICATION, 0
        };
        sbuf[2] = address;
        res = LTR__GenericCtlFunc(&module->ltr,
                               sbuf, sizeof(sbuf), NULL, 0,
                               LTRBOOT_ERROR_CALL_APPL, LTRBOOTAPI_TIMEOUT);
    }
    return res;
}
//-----------------------------------------------------------------------------
LTRBOOTAPI_DllExport(LPCSTR) LTRBOOT_GetErrorString(INT error)
{
    size_t i;
    for (i = 0; i < sizeof(ErrorStrings) / sizeof(ErrorStrings[0]); i++)
    {
        if (ErrorStrings[i].code == error)
            return ErrorStrings[i].message;
    }
    return LTR_GetErrorString(error);
}
//-----------------------------------------------------------------------------

#ifdef _WIN32
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
    {
        return 1;
    }
#endif
//---------------------------------------------------------------------------
