/*
 * Copyright (c) 2018-2019 Texas Instruments Incorporated - http://www.ti.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *  ======== General.syscfg.js ========
 *  General configuration support
 */

"use strict";
/* global exports, system */

//console.log("load: ti/ndk/General");

let util = system.getScript("/ti/ndk/util.js");

/*
 *  ======== modules ========
 *  Express dependencies for other modules
 *
 *  Invoked on any configuration change to the given instance.
 */
function modules(inst)
{
    let modules = new Array();

    modules.push({
        name: "rtos",
        moduleName: "/ti/drivers/RTOS"
    });

    return (modules);
}

/*
 *  ======== moduleInstances ========
 */
function moduleInstances(inst)
{
    let modules = new Array();

    modules.push({
        name: "emac",
        moduleName: "/ti/drivers/EMAC"
    });

    return (modules);
}

/*
 *  ======== onChange_ndkThrdCodeGen ========
 */
function onChange_ndkThrdCodeGen(inst, ui)
{
    let ndkStackThrd = (inst.stackThreadUser == "");
    let ndkThrdCodeGen = (ndkStackThrd && inst.enableCodeGeneration);

    ui.netSchedulerPri.readOnly = !ndkThrdCodeGen;
    ui.ndkTickPeriod.readOnly = !ndkStackThrd;
    ui.netSchedulerOpMode.readOnly = !ndkThrdCodeGen;

    /* ndkThreadPri always used */
    ui.lowTaskPriLevel.readOnly = !ndkThrdCodeGen;
    ui.normTaskPriLevel.readOnly = !ndkThrdCodeGen;
    ui.highTaskPriLevel.readOnly = !ndkThrdCodeGen;
    ui.kernTaskPriLevel.readOnly = !ndkThrdCodeGen;

    /* ndkThreadStackSize always used */
    ui.lowTaskStackSize.readOnly = !ndkThrdCodeGen;
    ui.normTaskStackSize.readOnly = !ndkThrdCodeGen;
    ui.highTaskStackSize.readOnly = !ndkThrdCodeGen;

    ui.pktNumFrameBufs.readOnly = !inst.enableCodeGeneration;
    ui.pktSizeFrameBuf.readOnly = !inst.enableCodeGeneration;
    ui.pbmDataSection.readOnly = !inst.enableCodeGeneration;

    ui.memRawPageSize.readOnly = !inst.enableCodeGeneration;
    ui.memRawPageCount.readOnly = !inst.enableCodeGeneration;
    ui.memDataSection.readOnly = !inst.enableCodeGeneration;

    ui.stackBeginHook.readOnly = !ndkThrdCodeGen;
    ui.stackInitHook.readOnly = !ndkThrdCodeGen;
    ui.stackDeleteHook.readOnly = !ndkThrdCodeGen;
    ui.stackRebootHook.readOnly = !ndkThrdCodeGen;

    ui.serviceReportHook.readOnly = !inst.enableCodeGeneration;
    ui.networkOpenHook.readOnly = !ndkThrdCodeGen;
    ui.networkCloseHook.readOnly = !ndkThrdCodeGen;
    ui.networkIPAddrHook.readOnly = !ndkThrdCodeGen;

    ui.hostName.readOnly = !inst.enableCodeGeneration;
}

/*
 *  ======== onChange_netConfig ========
 */
function onChange_netConfig(inst, ui)
{
    misc.needs_u32cval = false;

    if (inst.lowTaskStackSize != defval.lowTaskStackSize) {
        misc.needs_u32cval = true;
        return;
    }
    if (inst.normTaskStackSize != defval.normTaskStackSize) {
        misc.needs_u32cval = true;
        return;
    }
    if (inst.highTaskStackSize != defval.highTaskStackSize) {
        misc.needs_u32cval = true;
        return;
    }
}

/*
 *  ======== onChange_address ========
 */
function onChange_address(inst, ui)
{
    if (inst.address == "") {
        return;
    }

    /* allow only digit (base-10) and dot characters */
    inst.address = inst.address.replace(/[^\d\.]/g, "");
}

/*
 *  ======== onChange_gatewayIpAddr ========
 */
function onChange_gatewayIpAddr(inst, ui)
{
    if (inst.gatewayIpAddr == "") {
        return;
    }

    /* allow only digit (base-10) and dot characters */
    inst.gatewayIpAddr = inst.gatewayIpAddr.replace(/[^\d\.]/g, "");
}

/*
 *  ======== onChange_localIPA ========
 */
function onChange_localIPA(inst, ui)
{
    switch (inst.localIPA) {
        case "dhcpIPA":
            ui.IfIdxValid.readOnly = false;
            ui.ResolveIP.readOnly = false;
            ui.CallByIP.readOnly = false;
            ui.RestartIPTerm.readOnly = false;
            ui.address.readOnly = true;
            inst.address = defval.address;
            ui.mask.readOnly = true;
            inst.mask = defval.mask;
            ui.gatewayIpAddr.readOnly = true;
            inst.gatewayIpAddr = defval.gatewayIpAddr;
            ui.domainName.readOnly = true;
            inst.domainName = defval.domainName;
            break;

        case "staticIPA":
            ui.IfIdxValid.readOnly = true;
            inst.IfIdxValid = defval.IfIdxValid;
            ui.ResolveIP.readOnly = true;
            inst.ResolveIP = defval.ResolveIP;
            ui.CallByIP.readOnly = true;
            inst.CallByIP = defval.CallByIP;
            ui.RestartIPTerm.readOnly = true;
            inst.RestartIPTerm = defval.RestartIPTerm;
            ui.address.readOnly = false;
            ui.mask.readOnly = false;
            ui.gatewayIpAddr.readOnly = false;
            ui.domainName.readOnly = false;
            break;

        case "noneIPA":
            ui.IfIdxValid.readOnly = true;
            inst.IfIdxValid = defval.IfIdxValid;
            ui.ResolveIP.readOnly = true;
            inst.ResolveIP = defval.ResolveIP;
            ui.CallByIP.readOnly = true;
            inst.CallByIP = defval.CallByIP;
            ui.RestartIPTerm.readOnly = true;
            inst.RestartIPTerm = defval.RestartIPTerm;
            ui.address.readOnly = true;
            inst.address = defval.address;
            ui.mask.readOnly = true;
            inst.mask = defval.mask;
            ui.gatewayIpAddr.readOnly = true;
            inst.gatewayIpAddr = defval.gatewayIpAddr;
            ui.domainName.readOnly = true;
            inst.domainName = defval.domainName;
            break;
    }
}

/*
 *  ======== onChange_externDnsServIp ========
 */
function onChange_externDnsServIp(inst, ui)
{
    if (inst.externDnsServIp == "") {
        return;
    }

    /* allow only digit (base-10) and dot characters */
    inst.externDnsServIp = inst.externDnsServIp.replace(/[^\d\.]/g, "");
}

/*
 *  ======== onChange_enableExtDNS ========
 */
function onChange_enableExtDNS(inst, ui)
{
    ui.externDnsServIp.readOnly = !inst.enableExtDNS;
    if (!inst.enableExtDNS) {
        inst.externDnsServIp = defval.externDnsServIp;
    }
}

/*
 *  ======== validate ========
 *  Validate given instance and report conflicts
 *
 *  This function is not allowed to modify the instance state.
 */
function validate(inst, vo, getRef)
{
    let rtos = system.modules["/ti/drivers/RTOS"];

    switch (rtos.$static.name) {
        case "<none>":
        case "NoRTOS":
            vo.logError("Must select an RTOS (required by NDK)",
                rtos.$static, "name");
            break;
    }

    /* config.address */
    if (!util.validateIPAddr(inst.address)) {
        vo["address"].errors.push("Invalid IP address");
    }

    /* config.gatewayIpAddr */
    if (!util.validateIPAddr(inst.gatewayIpAddr)) {
        vo["gatewayIpAddr"].errors.push("Invalid IP address");
    }

    /* config.externDnsServIp */
    if (!util.validateIPAddr(inst.externDnsServIp)) {
        vo["externDnsServIp"].errors.push("Invalid IP address");
    }
}

/*
 *  ======== defval ========
 */
let defval = {
    IfIdxValid: true,
    ResolveIP: false,
    CallByIP: false,
    RestartIPTerm: false,
    address: "0.0.0.0",
    mask: "255.255.255.0",
    gatewayIpAddr: "0.0.0.0",
    domainName: "demo.net",

    externDnsServIp: "0.0.0.0",

    netSchedulerPri:    "NC_PRIORITY_LOW",
    ndkTickPeriod:      100,
    netSchedulerOpMode: "NC_OPMODE_INTERRUPT",
    ndkThreadPri:       5, /* same as normTaskPriLevel */
    ndkThreadStackSize: 8192, /* same as ndkTaskStaskSize */

    /* network task priority levels */
    lowTaskPriLevel:  3,
    normTaskPriLevel: 5,
    highTaskPriLevel: 7,
    kernTaskPriLevel: 9,

    /* network configuration defaults */
    lowTaskStackSize:  3072,
    normTaskStackSize: 4096,
    highTaskStackSize: 5120,

    /* TCP layer configuration defaults */
    tcpTxBufSize: 8192,
    tcpRxBufSize:  8192,
    tcpRxBufLimit: 8192,

    /* UDP layer configuration defaults */
    udpRxBufSize: 8192
};

/*
 *  ======== misc ========
 */
let misc = {
    needs_u32cval: false
};

/*
 *  ======== longDescription ========
 *  Intro splash on GUI
 */
let longDescription =
    "High level NDK stack configuration and settings. Use this module " +
    "to configure stack size, task priority, operating mode of the NDK " +
    "scheduler, and user hook functions.";

let ipOptions = [
{
        name: "hostName",
        displayName: "Client hostname",
        default: "tisoc",
        longDescription: `
Add our client hostname to configuration (to be claimed in all connected domains)

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_hostName)`,
        documentation: `
This translates directly into the following runtime call to
[CfgAddEntry()](html/group__ti__ndk__inc__nettools__inc____Cfg.html#ga72795e289e7a5e347b54b94f40667dc2).

    unsigned char *hostName = YOUR_CONFIGURED_VALUE;

    CfgAddEntry(hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0,
                 strlen(hostName), hostName, 0);
`
    },
    {
        name: "localIPA",
        displayName: "Local IP address configuration",
        onChange: onChange_localIPA,
        default: "dhcpIPA",
        options: [
            {
                name: "dhcpIPA",
                displayName: "Use DHCP to obtain IP address"
            },
            {
                name: "staticIPA",
                displayName: "Enable static IP address"
            },
            {
                name: "noneIPA",
                displayName: "Do not configure an IP address"
            }
        ]
    },
    {
        displayName: "DHCP Flags",
        config: [
            {
                name: "IfIdxValid",
                displayName: "Interface index is valid",
                default: defval.IfIdxValid,
                readOnly: false,
                hidden: true,
                longDescription: `
CIS_FLG_IFIDXVALID - Specifies if the IfIdx field is valid.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_IfIdxValid)`,
                documentation: `
This setting is part of the common argument structure for NDK services. It alters
the Mode field documentated in
[NDK API Guide](NDK_API_Reference.html#common-argument-structure).
        `
            },
            {
                name: "ResolveIP",
                displayName: "Resolve interface to IP address",
                default: defval.ResolveIP,
                readOnly: false,
                hidden: true,
                longDescription: `
CIS_FLG_RESOLVEIP - Requests that IfIdx be resolved to an IP address before
service execution is initiated.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_ResolveIP)`,
                documentation: `
This setting is part of the common argument structure for NDK services. It alters
the Mode field documentated in
[NDK API Guide](NDK_API_Reference.html#common-argument-structure).
        `
            },
            {
                name: "CallByIP",
                displayName: "Call using IP",
                default: defval.CallByIP,
                readOnly: false,
                hidden: true,
                longDescription: `
CIS_FLG_CALLBYIP - Specifies that the service should be invoked by IP address

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_CallByIP)`,
        documentation: `
This setting is part of the common argument structure for NDK services. It alters
the Mode field documentated in
[NDK API Guide](NDK_API_Reference.html#common-argument-structure).
        `
            },
            {
                name: "RestartIPTerm",
                displayName: "Restart service on IPTERM",
                default: defval.RestartIPTerm,
                readOnly: false,
                hidden: true,
                longDescription: `
CIS_FLG_RESTARTIPTERM - A service that is dependent on a valid IP address.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_RestartIPTerm)`,
                documentation: `
This setting is part of the common argument structure for NDK services. It alters
the Mode field documentated in
[NDK API Guide](NDK_API_Reference.html#common-argument-structure).
        `
            },
        ]
    },
    {
        name: "ifIdx",
        displayName: "Physical device index for IP address",
        hidden: true,
        default: 1
    },
    {
        name: "address",
        displayName: "Static IP address",
        onChange: onChange_address,
        default: defval.address,
        readOnly: true,
        description: "Enter a valid address for static IP configuration",
        longDescription: `
The static IPv4 address to be used.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_address)`,
        documentation: `
The IP Mask must be set in conjunction with this setting.
This translates directly into the following runtime call to.
[CfgAddEntry()](html/group__ti__ndk__inc__nettools__inc____Cfg.html#ga72795e289e7a5e347b54b94f40667dc2).

    char *LocalIPAddr = YOUR_CONFIGURED_ADDRESS_VALUE;
    char *LocalIPMask = YOUR_CONFIGURED_MASK_VALUE;
    char *DomainName  = YOUR_CONFIGURED_DOMAIN_VALUE;

    /* setup manual IP address */
    memset(&NA, 0, sizeof(NA));
    NA.IPAddr = inet_addr(LocalIPAddr);
    NA.IPMask = inet_addr(LocalIPMask);
    strcpy(NA.Domain, DomainName);
    NA.NetType = 0;

    CfgAddEntry(hCfg, CFGTAG_IPNET, 1, 0,
            sizeof(CI_IPNET), (unsigned char *)&NA, 0);
`
    },
    {
        name: "mask",
        displayName: "IP mask",
        default: defval.mask,
        readOnly: true,
        description: "Must be specified when using a static IP address",
        longDescription: `
Used for manual/static IP configuration.  If configuring a static IP,
this must be set to a valid mask value.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_mask)`,
        documentation: `
The IP Mask must be set in conjunction with the static IP address setting.
This translates directly into the following runtime call to.
[CfgAddEntry()](html/group__ti__ndk__inc__nettools__inc____Cfg.html#ga72795e289e7a5e347b54b94f40667dc2).

    char *LocalIPAddr = YOUR_CONFIGURED_ADDRESS_VALUE;
    char *LocalIPMask = YOUR_CONFIGURED_MASK_VALUE;
    char *DomainName  = YOUR_CONFIGURED_DOMAIN_VALUE;

    /* setup manual IP address */
    memset(&NA, 0, sizeof(NA));
    NA.IPAddr = inet_addr(LocalIPAddr);
    NA.IPMask = inet_addr(LocalIPMask);
    strcpy(NA.Domain, DomainName);
    NA.NetType = 0;

    CfgAddEntry(hCfg, CFGTAG_IPNET, 1, 0,
            sizeof(CI_IPNET), (unsigned char *)&NA, 0);
`
    },
    {
        name: "gatewayIpAddr",
        displayName: "Gateway IP address",
        onChange: onChange_gatewayIpAddr,
        default: defval.gatewayIpAddr,
        readOnly: true,
        description: "Must be specified when using a static IP address",
        longDescription: `
Used for manual/static IP configuration.  If configuring a static IP,
this must be set to the IP address of the gateway.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_gatewayIpAddr)`,
        documentation: `
The gateway IP address must be set in conjunction with the static IP address setting.
This translates directly into the following runtime call to.
[CfgAddEntry()](html/group__ti__ndk__inc__nettools__inc____Cfg.html#ga72795e289e7a5e347b54b94f40667dc2).

    char *GatewayIP = YOUR_CONFIGURED_VALUE;

    memset(&RT, 0, sizeof(RT));
    RT.IPDestAddr = 0;
    RT.IPDestMask = 0;
    RT.IPGateAddr = inet_addr(GatewayIP);

    CfgAddEntry(hCfg, CFGTAG_ROUTE, 0, 0,
            sizeof(CI_ROUTE), (unsigned char *)&RT, 0);
`
    },
    {
        name: "domainName",
        displayName: "Network domain name",
        default: defval.domainName,
        readOnly: true,
        description: "Must be specified when using a static IP address",
        longDescription: `
Used for manual/static IP configuration.  If configuring a static IP,
this must be set to the IP address of the gateway.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_domainName)`,
        documentation: `
The domain name must be set in conjunction with the static IP address setting.
This translates directly into the following runtime call to.
[CfgAddEntry()](html/group__ti__ndk__inc__nettools__inc____Cfg.html#ga72795e289e7a5e347b54b94f40667dc2).

    char *LocalIPAddr = YOUR_CONFIGURED_ADDRESS_VALUE;
    char *LocalIPMask = YOUR_CONFIGURED_MASK_VALUE;
    char *DomainName  = YOUR_CONFIGURED_DOMAIN_VALUE;

    /* setup manual IP address */
    memset(&NA, 0, sizeof(NA));
    NA.IPAddr = inet_addr(LocalIPAddr);
    NA.IPMask = inet_addr(LocalIPMask);
    strcpy(NA.Domain, DomainName);
    NA.NetType = 0;

    CfgAddEntry(hCfg, CFGTAG_IPNET, 1, 0,
            sizeof(CI_IPNET), (unsigned char *)&NA, 0);
`
    },
    {
        name: "dhcpClientPcbServer",
        displayName: "Service report function used by DHCP",
        default: "serviceReport",
        longDescription: `
Service report function used by DHCP. The default value will use the report
function generated by SysConfig.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_dhcpClientPcbServer)`,
        documentation: `
Information on adding your own service report report function can be found in the
[NDK User's Guide](NDK_Users_Guide.html#adding-status-report-services).
`
    },
    {
        name: "NetType",
        hidden: true,
        default: 0
    }
];

let tcpOptions = [
    {
        name: "tcpTxBufSize",
        displayName: "TCP transmit buffer size",
        default: defval.tcpTxBufSize,
        description: "Default TCP send buffer size (bytes)",
        longDescription: `
Sets the default size (in bytes) of the TCP send buffer

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_tcpTxBufSize)`,
        documentation: `
This translates directly into the following runtime call to
[CfgAddEntry()](html/group__ti__ndk__inc__nettools__inc____Cfg.html#ga72795e289e7a5e347b54b94f40667dc2).

    uint32_t transmitBufSize = YOUR_CONFIGURED_VALUE;

    CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPTXBUF, CFG_ADDMODE_UNIQUE,
            sizeof(uint32_t), (unsigned char *)&transmitBufSize, NULL);
`
    },
    {
        name: "tcpRxBufSize",
        displayName: "TCP receive buffer size (copy mode)",
        default: defval.tcpRxBufSize,
        description: "Default TCP receive size (bytes)",
        longDescription: `
Sets the default size (in bytes) of the TCP receive buffer

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_tcpRxBufSize)`,
        documentation: `
This translates directly into the following runtime call to
[CfgAddEntry()](html/group__ti__ndk__inc__nettools__inc____Cfg.html#ga72795e289e7a5e347b54b94f40667dc2).

    uint32_t receiveBufSize = YOUR_CONFIGURED_VALUE;

    CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPRXBUF, CFG_ADDMODE_UNIQUE,
            sizeof(uint32_t), (unsigned char *)&receiveBufSize, NULL);
`
    },
    {
        name: "tcpRxBufLimit",
        displayName: "TCP receive size maximum (non-copy mode)",
        default: defval.tcpRxBufLimit,
        description: "Default maximum TCP receive size (bytes)",
        longDescription: `
Sets the default size (in bytes) of the maximum TCP receive buffer

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_tcpRxBufLimit)`,
        documentation: `
This translates directly into the following runtime call to
[CfgAddEntry()](html/group__ti__ndk__inc__nettools__inc____Cfg.html#ga72795e289e7a5e347b54b94f40667dc2).

    uint32_t receiveBufLimit = YOUR_CONFIGURED_VALUE;

    CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPRXLIMIT, CFG_ADDMODE_UNIQUE,
            sizeof(uint32_t), (unsigned char *)&receiveBufLimit, NULL);
`
    }
];

let udpOptions = [
    {
        name: "udpRxBufSize",
        displayName: "UDP receive buffer size",
        default: defval.udpRxBufSize,
        longDescription: `
Sets the default size (in bytes) of the maximum UDP receive buffer

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_udpRxBufSize)`,
        documentation: `
This translates directly into the following runtime call to
[CfgAddEntry()](html/group__ti__ndk__inc__nettools__inc____Cfg.html#ga72795e289e7a5e347b54b94f40667dc2).

    uint32_t udpRxBufSize = YOUR_CONFIGURED_VALUE;

    CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKUDPRXLIMIT, CFG_ADDMODE_UNIQUE,
            sizeof(uint32_t), (unsigned char *)&udpRxBufSize, NULL);
`
    }
];

let externalDSNOptions = [
    {
        name: "enableExtDNS",
        displayName: "Define external DNS server",
        default: false,
        onChange: onChange_enableExtDNS
    },
    {
        name: "externDnsServIp",
        displayName: "External DNS server address",
        onChange: onChange_externDnsServIp,
        default: "0.0.0.0",
        readOnly: true,
        description: "Used to specify an external DNS Server.",
        longDescription: `
Use this to specify which external DNS server to use.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_externDnsServIp)`,
        documentation: `
This generates the code detailed in the Statically Defined DNS Server section
of the
[NDK User's Guide](NDK_Users_Guide.html#using-a-statically-defined-dns-server).
Note that the DHCP service will need to be using the serviceReport() function
for service reports for the code to generate properly.
`
    }
];

let netSchedulerTaskOptions = [
    {
        name: "netSchedulerPri",
        displayName: "Network Task Scheduler Task Priority",
        default: defval.netSchedulerPri,
        options: [
            {
                name: "NC_PRIORITY_LOW",
                displayName: "Low Priority"
            },
            {
                name: "NC_PRIORITY_HIGH",
                displayName: "High Priority"
            }
        ],
        description: "The priority level at which the NDK net scheduler " +
            "task runs.",
        longDescription: `
Set the NDK scheduler Task's priority relative to other networking Tasks in
the system.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_externDnsServIp)`,
        documentation: `
This translates directly into the following runtime call to
[NC_SystemOpen()](html/group__ti__ndk__inc__netctrl__NC.html#ga07a431ba384014587a24666c8532f505).

    int priority = YOUR_CONFIGURED_VALUE;

    rc = NC_SystemOpen(priority, NC_OPMODE_INTERRUPT );
`
    },
    {
        name: "ndkTickPeriod",
        displayName: "NDK heartbeat (clock ticks)",
        default: defval.ndkTickPeriod,
        description: "Tick period in Clock ticks for the NDK heartbeat.",
        longDescription: `
Lets you adjust the NDK heartbeat rate

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_ndkTickPeriod)`,
        documentation: `
The default is 100ms, and is created with POSIX apis, so it will function the
same in both TIRTOS and FreeRTOS.
`
    },
    {
        name: "netSchedulerOpMode",
        displayName: "Network scheduler operating mode",
        default: defval.netSchedulerOpMode,
        options: [
            {
                name: "NC_OPMODE_POLLING",
                displayName: "Polling"
            },
            {
                name: "NC_OPMODE_INTERRUPT",
                displayName: "Interrupt"
            }
        ],
        description: "The manner at which the NDK net scheduler task runs.",
        longDescription: `
Set to either Polling Mode (NC_OPMODE_POLLING) or Interrupt Mode
(NC_OPMODE_INTERRUPT), and determines when the scheduler attempts to execute.
Interrupt mode is used in the vast majority of applications. Note that
polling mode attempts to run continuously, so when polling is used, a low
priority must be used.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_ndkTickPeriod)`,
        documentation: `
This translates directly into the following runtime call to
[NC_SystemOpen()](html/group__ti__ndk__inc__netctrl__NC.html#ga07a431ba384014587a24666c8532f505).

    int mode = YOUR_CONFIGURED_VALUE;

    rc = NC_SystemOpen(NC_PRIORITY_HIGH, mode);
`
    }
];

let netTaskPriLevels = [
    {
        name: "ndkThreadPri",
        displayName: "Priority level for the NDK stack task",
        default: defval.ndkThreadPri,
        longDescription: `
Sets the priority of the generated NDK task ndkStackThread()

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_ndkThreadPri)`,
        documentation: `
This function will ultimately startup the stack
`
    },
    {
        name: "lowTaskPriLevel",
        displayName: "Priority level for low priority NDK tasks",
        default: defval.lowTaskPriLevel,
        description: "Sets the priority value for low priority NDK tasks.",
        longDescription: `
Allows you to configure the priority level for network tasks

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_lowTaskPriLevel)`,
        documentation: `
Set the priority for the macro OS_TASKPRILOW that is used in the call to
[TaskCreate()](NDK_API_Reference.html#taskcreate-create-a-task-thread).

For more information on NDK task priorities see the
[NDK User's Guide](NDK_Users_Guide.html#priority-levels-for-network-tasks).
`
    },
    {
        name: "normTaskPriLevel",
        displayName: "Priority level for normal priority NDK tasks",
        default: defval.normTaskPriLevel,
        description: "Sets the priority value for normal priority NDK tasks.",
        longDescription: `
Allows you to configure the priority level for network tasks

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_normTaskPriLevel)`,
        documentation: `
Set the priority for the macro OS_TASKPRINORM that is used in the call to
[TaskCreate()](NDK_API_Reference.html#taskcreate-create-a-task-thread).

For more information on NDK task priorities see the
[NDK User's Guide](NDK_Users_Guide.html#priority-levels-for-network-tasks).
`
    },
    {
        name: "highTaskPriLevel",
        displayName: "Priority level for high priority NDK tasks",
        default: defval.highTaskPriLevel,
        description: "Sets the priority value for high priority NDK tasks.",
        longDescription: `
Allows you to configure the priority level for network tasks

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_highTaskPriLevel)`,
        documentation: `
Set the priority for the macro OS_TASKPRIHIGH that is used in the call to
[TaskCreate()](NDK_API_Reference.html#taskcreate-create-a-task-thread).

For more information on NDK task priorities see the
[NDK User's Guide](NDK_Users_Guide.html#priority-levels-for-network-tasks).
`
    },
    {
        name: "kernTaskPriLevel",
        displayName: "NDK kernel level priority",
        default: defval.kernTaskPriLevel,
        description: "Sets the value for NDK kernel priority",
        longDescription: `
Allows you to configure the NDK kernel level priority.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_kernTaskPriLevel)`,
        documentation: `
Tasks (threads?) enter kernel mode during an llEnter()/llExit() block, during
which their priority will be raised to the level specified in this
configuration parameter.

Note that this only applies when the stack is configured to use priority
exclusion (not semaphores).

For more information on llEnter()/llExit(). See the
[NDK User's Guide](NDK_Users_Guide.html#choosing-the-llenterllexit-exclusion-method).
`
    }
];

let netTaskStkSizes = [
    {
        name: "ndkThreadStackSize",
        displayName: "Default stack size for the main network task (bytes)",
        default: defval.ndkThreadStackSize,
        description: "Stack size of the generated NDK task ndkStackThread()",
        longDescription: `
Sets the stack size of the generated NDK task ndkStackThread()

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_ndkThreadStackSize)`,
        documentation: `
This function will ultimately startup the stack
`
    },
    {
        name: "lowTaskStackSize",
        displayName: "Default stack size for low priority NDK tasks (bytes)",
        default: defval.lowTaskStackSize,
        onChange: onChange_netConfig,
        description: "Set the default stack size for low priority NDK tasks.",
        longDescription: `
Allows you to configure the stack size for network tasks

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_lowTaskStackSize)`,
        documentation: `
Set the priority for the macro OS_TASKSTKLOW that is used in the call to
[TaskCreate()](NDK_API_Reference.html#taskcreate-create-a-task-thread).
`
    },
    {
        name: "normTaskStackSize",
        displayName: "Default stack size for normal priority NDK tasks (bytes)",
        default: defval.normTaskStackSize,
        onChange: onChange_netConfig,
        description: "Set the default stack size for normal priority NDK tasks.",
        longDescription: `
Allows you to configure the stack size for network tasks

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_normTaskStackSize)`,
        documentation: `
Set the priority for the macro OS_TASKSTKNORM that is used in the call to
[TaskCreate()](NDK_API_Reference.html#taskcreate-create-a-task-thread).
`
    },
    {
        name: "highTaskStackSize",
        displayName: "Default stack size for high priority NDK tasks (bytes)",
        default: defval.highTaskStackSize,
        onChange: onChange_netConfig,
        description: "Set the default stack size for high priority NDK tasks.",
        longDescription: `
Allows you to configure the stack size for network tasks

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_highTaskStackSize)`,
        documentation: `
Set the priority for the macro OS_TASKSTKHIGH that is used in the call to
[TaskCreate()](NDK_API_Reference.html#taskcreate-create-a-task-thread).
`
    }
];

let pbmBuffers = [
    {
        name: "pktNumFrameBufs",
        displayName: "Number of frames",
        default: 10,
        description: "Packet Buffer Manager (PBM) number of frames",
        longDescription: `
Sets the number of frames in the Packet Buffer Manager

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_pktNumFrameBufs)`,
        documentation: `
For more information on the Packet Buffer Manager see the
[NDK User's Guide](NDK_Users_Guide.html#packet-buffer-manager-pbm.c).
`
    },
    {
        name: "pktSizeFrameBuf",
        displayName: "Frame buffer size (bytes)",
        default: 1536,
        description: "Packet Buffer Manager (PBM) size frame buffer",
        longDescription: `
Sets the frame buffer size in the Packet Buffer Manager

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_pktSizeFrameBuf)`,
        documentation: `
For more information on the Packet Buffer Manager see the
[NDK User's Guide](NDK_Users_Guide.html#packet-buffer-manager-pbm.c).
`
    },
    {
        name: "pbmDataSection",
        displayName: "Buffer data section",
        default: ".bss:NDK_PACKETMEM",
        description: "Packet Buffer Manager (PBM) buffer data section",
        longDescription: `
Defines the memory section used to place the the PBM frame buffer array.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_pbmDataSection)`,
        documentation: `
For more information on the Packet Buffer Manager see the
[NDK User's Guide](NDK_Users_Guide.html#packet-buffer-manager-pbm.c).
`
    }
];

let memManagerBuffs = [
    {
        name: "memRawPageSize",
        displayName: "Page size (bytes)",
        default: 3072,
        description: "Memory Manager page size",
        longDescription: `
Sets the page size for the NDK's memory allocation system.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_memRawPageSize)`,
        documentation: `
For more information on the memory allocation system see the
[NDK User's Guide](NDK_Users_Guide.html#memory-allocation-system-mem.c).
`
    },
    {
        name: "memRawPageCount",
        displayName: "Number of pages",
        default: 6,
        description: "Memory Manager page count",
        longDescription: `
Sets the number of pages for the NDK's memory allocation system.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_memRawPageCount)`,
        documentation: `
For more information on the memory allocation system see the
[NDK User's Guide](NDK_Users_Guide.html#memory-allocation-system-mem.c).
`
    },
    {
        name: "memDataSection",
        displayName: "Buffer data section",
        default: ".bss:NDK_MMBUFFER",
        description: "Memory Manager buffer data section",
        longDescription: `
Defines the memory section used to place the Memory Manager's allocation pool
buffer

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_memRawPageSize)`,
        documentation: `
For more information on the memory allocation system see the
[NDK User's Guide](NDK_Users_Guide.html#memory-allocation-system-mem.c).
`
    }
];

let socketOptions = [
    {
        name: "maxSockFileDesc",
        displayName: "Maximum number of socket file descriptors",
        default: 10,
        description: "Determine the size of the socket file descriptor table"
    }
];

let stkThreadHooks = [
    {
        name: "stackBeginHook",
        displayName: "Stack thread begin hook",
        default: "",
        description: "User defined hook function to run in the NDK stack thread",
        longDescription: `
User defined hook function to run in the NDK stack
thread ndkStackThread(). This function will run at the very
beginning of the stack thread, before the call to NC_SystemOpen() is made. It
will not be passed any arguments.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_stackBeginHook)`,
        documentation: `
For more information on stack thread hooks see the
[NDK User's Guide](NDK_Users_Guide.html#global-hook-configuration).
`
    },
    {
        name: "stackInitHook",
        displayName: "Stack thread initialization hook",
        default: "",
        description: "User defined hook function to run in the NDK stack thread",
        longDescription: `
User defined hook function to run in the NDK stack thread
ndkStackThread(). This function will run immediately after
the function call to create a new configuration, CfgNew(), and will be passed
the handle to that configuration

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_stackInitHook)`,
        documentation: `
For more information on stack thread hooks see the
[NDK User's Guide](NDK_Users_Guide.html#global-hook-configuration).
`
    },
    {
        name: "stackRebootHook",
        displayName: "Stack thread reboot hook",
        default: "",
        description: "User defined hook function to run in the NDK stack thread",
        longDescription: `
User defined hook function to run in the NDK stack thread
ndkStackThread(). This function will run immediately after
the return from NC_NetStart() and within the while() loop which contains the
NC_NetStart() call. It will be passed a handle to the configuration as well as
the valued returned from NC_NetStart.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_stackRebootHook)`,
        documentation: `
For more information on stack thread hooks see the
[NDK User's Guide](NDK_Users_Guide.html#global-hook-configuration).
`
    },
    {
        name: "stackDeleteHook",
        displayName: "Stack thread delete hook",
        default: "",
        description: "User defined hook function to run in the NDK stack thread",
        longDescription: `
User defined hook function to run in the NDK stack thread
ndkStackThread(). This function will run immediately after
exiting from the while() loop which contains the call to NC_NetStart(), but
before the subsequent calls to CfgFree(hCfg) and NC_SystemClose(). It will be
passed a handle to the configuration as well as the valued returned from
NC_NetStart.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_stackDeleteHook)`,
        documentation: `
For more information on stack thread hooks see the
[NDK User's Guide](NDK_Users_Guide.html#global-hook-configuration).
`
    }
];

let netCallbackHooks = [
    {
        name: "serviceReportHook",
        displayName: "Status report hook",
        default: "",
        description: "User defined hook function to run in the NDK status " +
            "report callback function",
        longDescription: `
User defined hook function to run in the NDK status report callback funtion,
serviceReport(). This function will run at the beginning
of the service report function and will be passed the the same arguments passed
to ti_ndk_config_Global_serviceReport(): Item, Status, Report and h.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_stackDeleteHook)`,
        documentation: `
For more information on the serviceReport() function see the
[NDK User's Guide](NDK_Users_Guide.html#adding-status-report-services).
`
    },
    {
        name: "networkOpenHook",
        displayName: "Network open hook",
        default: "",
        description: "User defined hook function to run inside the NDK " +
            "Network Start callback function, networkOpen().",
        longDescription: `
User defined hook function to run inside the NDK Network Start callback
function, networkOpen(). The Network Start callback function is called when
the stack is ready to begin the creation of application supplied network
tasks. This hook function will run immediately, upon entering the networkOpen()
function. Note that this function is called during the early stages of the
stack startup, and must return in order for the stack to resume operations.
It will not be passed any arguments.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_networkOpenHook)`,
        documentation: `
For more information on startup hooks see the
[NDK User's Guide](NDK_Users_Guide.html#global-hook-configuration).
`
    },
    {
        name: "networkCloseHook",
        displayName: "Network close hook",
        default: "",
        description: "User defined hook function to run in the NDK " +
            "Network Stop callback function, NetworkClose().",
        longDescription: `
User defined hook function to run in the NDK Network Stop callback function,
NetworkClose(). The Network Close callback function is called when the stack is
about to shut down. This hook function will run immediately, upon entering the
NetworkClose() function. It will not  be passed any arguments.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_networkCloseHook)`,
        documentation: `
For more information on startup hooks see the
[NDK User's Guide](NDK_Users_Guide.html#global-hook-configuration).
`
    },
    {
        name: "networkIPAddrHook",
        displayName: "Network IP address hook",
        default: "",
        description: "User defined hook function to run in the NDK " +
            "Network IP address callback function, NetworkIPAddr().",
        longDescription: `
User defined hook function to run in the NDK Network IP address callback function,
NetworkIPAddr(). The Network IP address callback function is called when an IP
address is added or removed from the system. This hook function will run
immediately, upon entering the NetworkIPAddr() function and is passed the same
arguments passed to NetworkIPAddr(): IPAddr, IfIdx, fAdd.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_networkIPAddrHook)`,
        documentation: `
For more information on startup hooks see the
[NDK User's Guide](NDK_Users_Guide.html#global-hook-configuration).
`
    }
];

/*
 *  ======== config ========
 *  Define the config params of the module instance
 */
let config = [
    {
        name: "ipv6",
        displayName: "Enable IPv6 support",
        hidden: true,
        default: true,
        description: "When selected, the IPv6 version of the NDK libraries " +
            "will be used, otherwise the IPv4 versions will be used."
    },
    {
        displayName: "IP Options",
        description: "IP Options",
        config: ipOptions,
        collapsed: false
    },
    {
        displayName: "TCP Options",
        config: tcpOptions
    },
    {
        displayName: "UDP Options",
        config: udpOptions
    },
    {
        displayName: "External DNS Options",
        config: externalDSNOptions
    },
    {
        displayName: "Network Scheduler Task Options",
        config: netSchedulerTaskOptions
    },
    {
        displayName: "Network Task Priority Levels",
        config: netTaskPriLevels
    },
    {
        displayName: "Network Task Stack Sizes",
        config: netTaskStkSizes
    },
    {
        displayName: "PBM Buffers",
        config: pbmBuffers
    },
    {
        displayName: "Memory Manager Buffers",
        config: memManagerBuffs
    },
    {
        displayName: "Socket Options",
        config: socketOptions
    },
    {
        displayName: "Stack Thread Hooks",
        config: stkThreadHooks
    },
    {
        displayName: "Network Callback Hooks",
        config: netCallbackHooks
    },
    {
        name: "stackThreadUser",
        displayName: "User NDK thread function",
        hidden: true,
        default: "",
        onChange: onChange_ndkThrdCodeGen,
        description: "Example: User_stackThreadFxn",
        longDescription: `
User defined stack function that will run instead of the generated
ndkStackThread.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_networkIPAddrHook)`,
        documentation: `
Only use your own stack thread if you do not want any of the generated SysConfig
content involved with starting up the stack.

If set, the user is responsible for defining the NDK stack thread, which has
no return value and has two parameters of type uintptr_t.

For example (C code):

  void MYMODULE_stackThreadUser(uintptr_t arg0, uintptr_t arg1);

The user is also responsible for creating the RTOS Clock
instance for the NDK 100ms heartbeat, calling appropriate NC_* APIs,
and adding the appropriate C run time configuration code that matches
the settings of the BIOS config file in the function. (e.g. if
configuring the Ip module, the stack thread must call NC_SystemOpen(),
'ti_ndk_config_ip_init(hCfg)', etc.).

For more information on the requirments for a user stack thread see the
[NDK User's Guide](NDK_Users_Guide.html#constructing-a-configuration-for-a-static-ip-and-gateway)
`
    },
    {
        name: "enableCodeGeneration",
        displayName: "Enable code generation",
        hidden: true,
        default: true,
        onChange: onChange_ndkThrdCodeGen,
        description: "Generate NDK stack thread and C configuration code",
        longDescription: `
Only disable this if you know what you are doing. Disableing will prevent any
of the NDK stack thread from generating.

[More ...](/ndk/ConfigDoc.html#ti_ndk_General_networkIPAddrHook)`,
        documentation: `
This setting is similar to the "User NDK thread function" setting, except it
will not even generate the code to start a stack thread.
`
    }
];

/*
 *  ======== tfxn ========
 *  Template helper functions
 */
let tfxn = {
    cisargs_mode: function(mod)
    {
        let flags = [];

        if (mod.$static.IfIdxValid) flags.push("CIS_FLG_IFIDXVALID");
        if (mod.$static.ResolveIP) flags.push("CIS_FLG_RESOLVEIP");
        if (mod.$static.CallByIP) flags.push("CIS_FLG_CALLBYIP");
        if (mod.$static.RestartIPTerm) flags.push("CIS_FLG_RESTARTIPTERM");

        if (flags.length == 0) {
            return ("0");
        }
        else {
            return (flags.join(" | "));
        }
    }
};

/*
 *  ======== base ========
 *  Module definition object
 */
let base = {
    displayName: "NDK Stack",
    description: "General network configuration",
    longDescription: longDescription,
    moduleStatic: {
        modules: modules,
        moduleInstances: moduleInstances,
        config: config,
        validate: validate
    },
    templates: {
        "/ti/ndk/Config.c.xdt": "/ti/ndk/General.Config.c.xdt"
    },
    defval: defval,
    misc: misc,
    tfxn: tfxn
};

/* export the module */
exports = base;
