Problem with MDC API

I am trying to use the MDC API for the FX30S but I am having some troubles and an error which is difficult to troubleshoot.
So I have followed these instructions:
https://docs.legato.io/15_08/c_mdc.html
And also these two:

The problem I am having is that this works (at times) and at times doesn`t work.
The problem seems to be with the handler which report a wrong status?
This is my code
static void SetNetworkConfiguration()
{
char ipAddr[100] = {0};
char gatewayAddr[100] = {0};
char dns1Addr[100] = {0};
char dns2Addr[100] = {0};
char systemCmd[200] = {0};
FILE* resolvFilePtr;
le_mdc_ConState_t state = LE_MDC_DISCONNECTED;
mode_t oldMask;

// Check the state
LE_ASSERT( le_mdc_GetSessionState(modemProfile, &state) == LE_OK );
LE_ASSERT( state == LE_MDC_CONNECTED );

// Get IP, gateway and DNS addresses for IPv4 or IPv6 connectivity
if ( le_mdc_IsIPv4(modemProfile) )
{
    LE_ASSERT(le_mdc_GetIPv4Address(modemProfile, ipAddr, sizeof(ipAddr)) == LE_OK);
    LE_INFO("%s", ipAddr);

    LE_ASSERT(le_mdc_GetIPv4GatewayAddress(modemProfile, gatewayAddr, sizeof(gatewayAddr))
                                                                                      == LE_OK);
    LE_INFO("%s", gatewayAddr);

    LE_ASSERT(le_mdc_GetIPv4DNSAddresses( modemProfile,
                                          dns1Addr, sizeof(dns1Addr),
                                          dns2Addr, sizeof(dns2Addr)) == LE_OK );
    LE_INFO("%s", dns1Addr);
    LE_INFO("%s", dns2Addr);

    snprintf(systemCmd, sizeof(systemCmd), "/sbin/route add default gw %s", gatewayAddr);
}
else if ( le_mdc_IsIPv6(modemProfile) )
{
    LE_ASSERT(le_mdc_GetIPv6Address(modemProfile, ipAddr, sizeof(ipAddr)) == LE_OK);
    LE_INFO("%s", ipAddr);

    LE_ASSERT(le_mdc_GetIPv6GatewayAddress(modemProfile, gatewayAddr, sizeof(gatewayAddr))
                                                                                      == LE_OK);
    LE_INFO("%s", gatewayAddr);

    LE_ASSERT(le_mdc_GetIPv6DNSAddresses( modemProfile,
                                          dns1Addr, sizeof(dns1Addr),
                                          dns2Addr, sizeof(dns2Addr)) == LE_OK );
    LE_INFO("%s", dns1Addr);
    LE_INFO("%s", dns2Addr);

    snprintf(systemCmd, sizeof(systemCmd), "/sbin/route -A inet6 add default gw %s",
                                            gatewayAddr);
}

sleep(5);

LE_DEBUG("%s", systemCmd);
LE_ASSERT( system(systemCmd) == 0 );

// allow fopen to create file with mode=644
oldMask = umask(022);

// open the resolver configuration
resolvFilePtr = fopen("/etc/resolv.conf", "w+");

if (resolvFilePtr == NULL)
{
    LE_ERROR("Unable to open resolv.conf: %m");
}
LE_ASSERT( resolvFilePtr != NULL );

LE_ASSERT( fprintf(resolvFilePtr, "nameserver %s\n", dns1Addr) > 0 );

if (dns2Addr[0] != '\0')
{
    LE_ASSERT( fprintf(resolvFilePtr, "nameserver %s\n", dns2Addr) > 0 );
}

LE_ASSERT( fclose(resolvFilePtr) == 0 );

// restore old mask
umask(oldMask);

}

static le_result_t ConnectModem(){
//create an handler for Data Connection state
char data[200];
char APN[11] = “telstra.wap”;
le_result_t rs;
LE_FATAL_IF(modemProfile == NULL, “Profile doesnt exist"); //set the PDP rs = le_mdc_SetPDP(modemProfile, LE_MDC_PDP_IPV4V6); LE_FATAL_IF(rs != LE_OK, "Couldnt set PDP.”);
//readback the PDP
le_mdc_Pdp_t ProfilePDP = le_mdc_GetPDP(modemProfile);
switch (ProfilePDP)
{
case LE_MDC_PDP_UNKNOWN:
LE_INFO(“PDP Unknown”);
break;
case LE_MDC_PDP_IPV4:
LE_INFO(“PDP IPv4”);
break;
case LE_MDC_PDP_IPV6:
LE_INFO(“IPDP Pv6”);
break;
case LE_MDC_PDP_IPV4V6:
LE_INFO(“PDP IPv4v6”);
break;
default:
LE_ERROR(“PDP unsupported %d”, ProfilePDP);
break;
}
//set APN
rs = le_mdc_SetAPN(modemProfile,&APN[0]);
LE_FATAL_IF(rs != LE_OK, “Couldn`t set APN.”);
rs = le_mdc_GetAPN(modemProfile, &data[0], sizeof(data));
if(LE_OK == rs)
LE_INFO(“APN: %s, %d”,data, rs);

LE_INFO("Try to Start Session.");
if (LE_OK == le_mdc_StartSession (modemProfile))
    LE_INFO("Modem is connecting.");

return LE_OK;

}

static void DataConnectionStateHandler(le_mdc_ProfileRef_t profileRef, le_mdc_ConState_t ConnectionState, void contextPtr)
{ /

LE_MDC_DISCONNECTED Data session is disconnected.
LE_MDC_AUTHENTICATING Authenticating data session.
LE_MDC_CONNECTED Data session is connected.
LE_MDC_SUSPENDING Suspending data session.
LE_MDC_INCOMING Incoming data session (MT-PDP context request)
*/
le_mdc_ConState_t state = LE_MDC_DISCONNECTED;
// Check the state
LE_ASSERT( le_mdc_GetSessionState(modemProfile, &state) == LE_OK );
if(ConnectionState != state)
LE_INFO(“State for modem doesn`t match”);

switch (ConnectionState)
{   
    case LE_MDC_DISCONNECTED:
        LE_INFO("Modem Disconnected.");
        LE_INFO("System will try to reconnect");
        //ConnectModem();
        break;
    case LE_MDC_AUTHENTICATING:
        LE_INFO("Modem Authenticating");
        break;
    case LE_MDC_CONNECTED:
        LE_INFO("Modem Just Connected");
        LE_INFO("Go to sleep for a few seconds..");
        sleep(3);
        LE_INFO("Waking up..");
        LE_INFO("Setup NETWORK configuration.");
        SetNetworkConfiguration(modemProfile);
        break;
    case LE_MDC_SUSPENDING:
        LE_INFO("Modem Suspending");
        break;
    case LE_MDC_INCOMING:
        LE_INFO("Modem Incoming");
        break;

    default:
        LE_ERROR("Unsupported MDC session state %d", ConnectionState);
        break;
}

}

COMPONENT_INIT
{
LE_INFO(“Checking modem configuration.”);
modemProfile = le_mdc_GetProfile(modemProfileIndex);
le_mdc_ConState_t modemState = LE_MDC_DISCONNECTED;

char data[200];
//Check if modem is already connected
LE_INFO("Create Handler for Connection State.");
le_mdc_SessionStateHandlerRef_t SessionStateHandler = le_mdc_AddSessionStateHandler(modemProfile, DataConnectionStateHandler, NULL);
LE_FATAL_IF(SessionStateHandler == NULL, "Session state handler not created!!");

//Connect modem
LE_ASSERT( le_mdc_GetSessionState(modemProfile, &modemState) == LE_OK );
if(modemState != LE_MDC_CONNECTED)
{
    LE_INFO("Will start connecting the modem");
    rs = ConnectModem(modemProfileIndex);
}

rs =  le_info_GetImei(&data[0], sizeof(data));
LE_INFO("IMEI: %s, %d",data, rs);
//now try to connect the router
return;

}

And the program fails at line:
LE_ASSERT( state == LE_MDC_CONNECTED );
However, the function only gets called by the handler “DataConnectionStateHandler” once the state of the modem is LE_MDC_CONNECTED, so I am a bit confused about why this is happening…
Anybody able to help about this problem?

don’t quite understand your problem…
do you see problem in CM tool?

I am not talking about the shell commands, trying to configure and start the modem data from a C source file.

if you don’t see problem in shell command, that means there is problem on your C program.
Then you can check the source code of CM tool and see what should be port to your application.

where do I find the source for the shell commands?

you can see here:

I have checked the source for the cm data but this is not exactly what I was asking.
The code I have used and written above is from the example code of Legato docs, my question is why the handler ConnectionState and the state returned from le_mdc_GetSessionState(modemProfile, &state) have different values?
This software systematically fails at LE_ASSERT( state == LE_MDC_CONNECTED ) when this function SetNetworkConfiguration is called by the handler only when the state is LE_MDC_CONNECTED.

The modem will run on bootup but it will not run on any new application download.

Is anybody able to provide an answer to this?
Thanks :slight_smile:

do you mean this line will make the program stopped?
LE_ASSERT( state == LE_MDC_CONNECTED )

Also you might need to try the latest test application which is quite different from yours:

I am testing this software on my target and it happens the same thing:

Feb 26 14:48:16 fx30s user.info Legato: INFO | supervisor[1138]/supervisor T=main | app.c app_Start() 3377 | Starting app ‘mdcTest’
Feb 26 14:48:16 fx30s user.info Legato: INFO | supervisor[1138]/supervisor T=main | app.c CreateFileLink() 1991 | Skipping file link ‘/legato/systems/current/apps/mdcTest/read-only/lib/libComponent_mdcTestComp.so’ to '/legato/systems/current/appsWriteable/mdcTest/li
Feb 26 14:48:16 fx30s user.info Legato: INFO | supervisor[1138]/supervisor T=main | app.c CreateFileLink() 1991 | Skipping file link ‘/legato/systems/current/apps/mdcTest/read-only/bin/mdcTest’ to ‘/legato/systems/current/appsWriteable/mdcTest/bin/mdcTest’: Already
Feb 26 14:48:16 fx30s user.info Legato: INFO | supervisor[1138]/supervisor T=main | proc.c proc_Start() 1389 | Starting process ‘mdcTest’ with pid 3659
Feb 26 14:48:16 fx30s user.info Legato: INFO | supervisor[3659]/supervisor T=main | proc.c proc_Start() 1354 | Execing ‘mdcTest’
Feb 26 14:48:16 fx30s user.debug Legato: DBUG | UNKNOWN[3659]/ T=main | _componentMain.c _mdcTestComp_Init() 29 | Initializing mdcTestComp component library.
Feb 26 14:48:16 fx30s user.debug Legato: DBUG | UNKNOWN[3659]/framework T=main | le_mdc_client.c DoConnectService() 355 | ======= Starting client for ‘mdcTest.mdcTestComp.le_mdc’ service ========
mdcTest[3659]/framework T=main | LE_FILENAME InitPool() 303 | Memory pool name ‘framework.msgs-LogControlProtocol’ is truncated to ‘framework.msgs-LogControlProtoc’
mdcTest[3659]/framework T=main | LE_FILENAME le_mem_ForceAlloc() 841 | Memory pool ‘framework.SigMonitor’ overflowed. Expanded to 1 blocks.
mdcTest[3659]/framework T=main | LE_FILENAME le_mem_ForceAlloc() 841 | Memory pool ‘framework.SigHandler’ overflowed. Expanded to 1 blocks.
mdcTest[3659]/mdcTest_exe T=main | _main.c main() 61 | == Starting Event Processing Loop ==
mdcTest[3659]/mdcTestComp T=main | mdcTest.c _mdcTestComp_COMPONENT_INIT() 612 | ======= MDC TEST STARTED =======
mdcTest[3659]/mdcTestComp T=main | mdcTest.c SetConfiguration() 352 | cid: 1 pdp: 1 apn: auto auth: 1 username: password:
mdcTest[3659]/framework T=MDC_Test | LE_FILENAME PThreadStartRoutine() 365 | Set nice level to 0.
mdcTest[3659]/framework T=MDC_Test | LE_FILENAME le_mem_ForceAlloc() 841 | Memory pool ‘framework.DestructorObjs’ overflowed. Expanded to 2 blocks.
mdcTest[3659]/framework T=MDC_Test | LE_FILENAME le_mem_ForceAlloc() 841 | Memory pool ‘.le_mdc_ClientThreadData’ overflowed. Expanded to 2 blocks.
mdcTest[3659]/framework T=MDC_Test | le_mdc_client.c DoConnectService() 355 | ======= Starting client for ‘mdcTest.mdcTestComp.le_mdc’ service ========
mdcTest[3659]/framework T=MDC_Test | LE_FILENAME le_mem_ForceAlloc() 841 | Memory pool ‘.le_mdc_ClientData’ overflowed. Expanded to 1 blocks.
======= MDC TEST_SYNC STARTED =======
mdcTest[3659]/mdcTestComp T=MDC_Test | mdcTest.c StateChangeHandler() 463 | ================================================
mdcTest[3659]/mdcTestComp T=MDC_Test | mdcTest.c StateChangeHandler() 464 | (int) le_mdc_GetProfileIndex(profileRef)=1
mdcTest[3659]/mdcTestComp T=MDC_Test | mdcTest.c StateChangeHandler() 465 | ConnectionStatus=2
mdcTest[3659]/mdcTestComp T=MDC_Test | mdcTest.c StateChangeHandler() 486 | ================================================
mdcTest[3659]/mdcTestComp T=main | mdcTest.c SetNetworkConfiguration() 386 | ipAddr=10.250.218.246
mdcTest[3659]/mdcTestComp T=main | mdcTest.c SetNetworkConfiguration() 390 | gatewayAddr=10.250.218.245
mdcTest[3659]/mdcTestComp T=main | mdcTest.c SetNetworkConfiguration() 395 | dns1Addr=10.5.68.232
mdcTest[3659]/mdcTestComp T=main | mdcTest.c SetNetworkConfiguration() 396 | dns2Addr=10.5.209.36
mdcTest[3659]/mdcTestComp T=MDC_Test | mdcTest.c StateChangeHandler() 463 | ================================================
mdcTest[3659]/mdcTestComp T=MDC_Test | mdcTest.c StateChangeHandler() 464 | (int) le_mdc_GetProfileIndex(profileRef)=1
mdcTest[3659]/mdcTestComp T=MDC_Test | mdcTest.c StateChangeHandler() 465 | ConnectionStatus=0
mdcTest[3659]/mdcTestComp T=MDC_Test | mdcTest.c StateChangeHandler() 481 | le_mdc_GetDisconnectionReasonExt(profileRef, 0)=45
Feb 26 14:48:16 fx30s user.debug Legato: DBUG | mdcTest[3659]/mdcTestComp T=MDC_Test | mdcTest.c StateChangeHandler() 482 | le_mdc_GetPlatformSpecificDisconnectionCodeExt(profileRef, 0)=1
Feb 26 14:48:16 fx30s user.debug Legato: DBUG | mdcTest[3659]/mdcTestComp T=MDC_Test | mdcTest.c StateChangeHandler() 486 | ================================================
mdcTest[3659]/mdcTestComp T=main | mdcTest.c SetNetworkConfiguration() 421 | /sbin/route add default gw 10.250.218.245
mdcTest[3659] | route: SIOCADDRT: Network is unreachable
mdcTest[3659]/mdcTestComp T=main | Assert Failed: ‘system(systemCmd) == 0’
supervisor[1138]/supervisor T=main | proc.c Process ‘mdcTest’ (PID: 3659) has exited with exit code 1.

Where it will initially connect, than the handler will return the DISCONNECT for unknown reason?
I am using this device with a telstra sim card in australia.
The only thing I did add to this code is a fixed APN name for the network:
const char * APN = “telstra.wap”;
LE_ASSERT(LE_OK == le_mdc_SetAPN(*profileRefPtr, APN));

And also removed the le_thread_Sleep for which I can`t find the include file in the legato workspace.

The APN I am certain it works correctly, as if I run the command from shell
cm data connect
It will connect properly.

Not sure if replacing the le_thread_Sleep with sleep is causing the issue, as I see documentation says this could cause bugs, but don`t think this is the problem.
The modem is disconnecting straight after connecting for no reason (as far as it looks).

I have problem in starting the data connection, do you know why?
logread.txt (12.8 KB)

Is there anybody able to help on clarifying how this mdc API should work?
As I said, on bootup the modem will start, but if I try to run the app when the device is already up and running, then it will not work with the message I have reported above.

can you check in your code if le_mdc_StopSession() is called?

I am not running my code but a copy an paste of the link you have sent, all beside the change I have indicated above, reaplcing le_thread_sleep with sleep and hardcoding the APN to the APN I am using.

I tried on another WP76, I don’t see any problem on running the application, you can see my logread.

logread_mdeTest.txt (22.8 KB)

root@swi-mdm9x28-wp:~# cm info
Device: WP7609
IMEI: 359782080100373
IMEISV: 6
FSN: WA803370311610
Firmware Version: SWI9X07Y_02.28[ 529.721111] i2c-msm-v2 78b8000.i2c: NACK: slave not responding, ensure its powered: msgs(n:1 cur:0 tx) bc(rx:0 tx:2) mode:FIFO slv_addr:0x3a MSTR_STS:0x001363c8 OPER:0x00000090
.03.05 000000 jenkins 2019/07/08 11:04:16
Bootloader Version: [ 529.740566] i2c-msm-v2 78b8000.i2c: NACK: slave not responding, ensure its powered: msgs(n:1 cur:0 tx) bc(rx:0 tx:2) mode:FIFO slv_addr:0x3a MSTR_STS:0x001363c8 OPER:0x00000090
SWI9X07Y_02.28.03.05 000000 jenkins 2019/07/08 11:04:16
MCU Version: 002.011
PRI Part Number (PN): 9908102
PRI Revision: 001.000
Carrier PRI Name: GENERIC
Carrier PRI Revision: 002.073_000
SKU: 1103843
Last Reset Cause: Power Down
Resets Count: Expected: 10226 Unexpected: 0

I cant get it to work, the only thing I can think of is another app using the same interface and so conditioning the handler in my app. When I have built my system, how can I am my own firmware release so to eliminate apps which I dont need?
i.e. the AirVantage is installed and if I remove it will come back after a reboot…

you might try to “app stop” the unwanted application.
Also you might try with default WP76 FW R13, I don’t see problem with it.

Tried with the app stop already, also tried with the app remove.
Will give it a go with the different firmware to see how it goes.

mmmhh, I have updated the firmware on the target using the WP77xx_Release13_GENERIC_GCF.exe and that seems to have broken the target.
No apps installed and I cant flash back the .cwe file from shell as the fwupdate app is not running anymore. I cant download my system either as I get:
sh: /legato/systems/current/bin/update: not found
cat: write error: Broken pipe
update failed

i tried on mangoh red +WP77 on FW R13 before, no problem is found.