Data mode to Command mode


#1

Hello all again ^_^.

I have a little one this time. I'm still programming a gprs modem. I can connect it using telnet. When I get connected, I enter in data mode. When I want to change, I know I have to use the "+++" string and the ADL_FCM_EVENT_V24_DATA_MODE_EXT event, but when I capture it, I don't know how to change to command mode. Can anyone help me with this? 

Oh!, and if I want to use the usual “login+password” before the user can send data, where is place to do it? Thank you all in advance :slight_smile:.

Tavo.

#2

If the callback returns TRUE, the switch to AT mode is accepted. If the callback return FALSE, it reswitches immedaitely to data mode.

If you want to go back to data mode at some later point, use adl_fcmSwitchV24State().


#3

Hello again. I still have a little doubt. What generates the ADL_FCM_EVENT_V24_DATA_MODE_EXT event?. I get perfectly connected, but the ´+++´ string doesn’t seem to generate anything… here is my code…

bool V24M_Ctrl_Handler ( adl_fcmEvent_e event ) {

	s8 result, debug;
	ascii rspStr[256];

    if ( event == ADL_FCM_EVENT_FLOW_OPENNED ) {
        
		// Change serial link to data mode
        TRACE ( ( LVL_SERIAL, "V24M_Ctrl_Handler: V24 link opened - change to data mode" ) );
		adl_atSendResponsePort ( ADL_AT_UNS, ADL_PORT_UART1, "+TR2RS\n\r" );
        result = adl_fcmSwitchV24State ( V24M_Handle, ADL_FCM_V24_STATE_DATA );
        if ( result != OK ) {

            TRACE ( ( LVL_SERIAL, "V24M_Ctrl_Handler: cannot change serial link to data mode" ) );
        }
    }
    if ( event == ADL_FCM_EVENT_FLOW_CLOSED ) {

        TRACE ( ( LVL_SERIAL, "V24M_Ctrl_Handler: V24 link closed" ) );
    }
    else if ( event == ADL_FCM_EVENT_V24_DATA_MODE ) {
		//Change AT mode to data mode
        TRACE ( ( LVL_SERIAL, "V24M_Ctrl_Handler: V24 link changed to data mode" ) );
        t2r_SerialCmdMode = FALSE;
		debug = adl_fcmSwitchV24State ( V24M_Handle, ADL_FCM_V24_STATE_DATA );
    }
    else if ( event == ADL_FCM_EVENT_V24_AT_MODE_EXT ) {
		//Change data mode to AT mode.
		TRACE ( ( LVL_SERIAL, "V24M_Ctrl_Handler: V24 link received +++ in data mode" ) );
        t2r_SerialCmdMode = TRUE;
		debug = adl_fcmSwitchV24State ( V24M_Handle, ADL_FCM_V24_STATE_AT );
    }
	else if ( event == ADL_FCM_EVENT_V24_AT_MODE ) {
		//Change data mode to AT mode.
		TRACE ( ( LVL_SERIAL, "V24M_Ctrl_Handler: V24 link received +++ in data mode" ) );
        t2r_SerialCmdMode = TRUE;
		debug = adl_fcmSwitchV24State ( V24M_Handle, ADL_FCM_V24_STATE_AT );
    }
    else if ( event == ADL_FCM_EVENT_V24_DATA_MODE_EXT ) {
        
		TRACE ( ( LVL_SERIAL, "V24M_Ctrl_Handler: V24 link received ATO in command mode" ) );
        t2r_SerialCmdMode = FALSE;
		debug = adl_fcmSwitchV24State ( V24M_Handle, ADL_FCM_V24_STATE_DATA );
    }
    else if ( event = ADL_FCM_EVENT_MEM_RELEASE )
        TRACE ( ( LVL_SERIAL, "V24M_Ctrl_Handler: V24 link memory release" ) );
    else
		TRACE ( ( LVL_SERIAL, "V24M_Ctrl_Handler: V24 link received other events" ) );
    
    return ( TRUE );
}

Thank you all in advance :slight_smile:


#4

Well, maybe you’re confused a bit :slight_smile:

If you use the ATD command from terminal, you’ll get the CONNECT message and now you’re in data mode. any characters you send, will arrive at the other end. If you send +++, that will switch the local side into command mode where you can use ATH to end the connection, ATO to get back to data mode, or any other command.
This +++ generates the ADL_FCM_EVENT_V24_AT_MODE_EXT notification, and the ATO generates ADL_FCM_EVENT_V24_DATA_MODE_EXT. LOCALLY!

If you use adl_callAnswer() or adl_callSetup() to make a call, the data are routed internally and are not even available at any UART, so the only way to switch mode (not that you need it) is to call adl_fcmSwitchV24State().

It seems you have something as the telnet client, and a Wavecom module as a telnet server. If this is so, there’s no way a client could generate any ADL_FCM_EVENT_V24_XX_MODE_XX on the other side. These are initiated locally: from wavecom’s UARTs, or from your code.

And you’ll have to handle the login dialog just as any data, since there’s no “before login” phase. You send the “Login:” text, and wait for an answer. Repeat for password. Then you can send a prompt and wait for commands.

HTH, Milan


#5

Wow, you’ve opened my eyes xD. Now I see I was lost :stuck_out_tongue:. I think I know how to do it now.
Just one more thing, about login and password. I can’t ask for a string just as in standard C IO (printf/scanf). My idea is to have a Login and a Password stored in flash memory, which i’ll compare with the user login and password. How can I ask the user for these? Thank you again for your help :slight_smile:.


#6

It’s not very easy. You need to use adl_fcmSendData() to send prompts and the data handler to receive responses. It would look like this:

s8 gsmFcmHandle; //filled somewhere else using adl_fcmSubscribe

enum {lostFirst, lostLogin, lostPassword, lostLoggedIn, lostFailed} LoginState;
ascii LoginBuffer[20];
int LoginBufferUsed;

void myTimer()
 {
  switch (LoginState)
   {
    case lostFirst:
     {
      adl_fcmSendData(gsmFcmHandle, "Login:\r\n", 8);
      LoginBufferUsed=0;
      LoginState=lostLogin;
     } break;
    //other cases handled in data handler
    case lostLoggedIn:
     {
      //logged in
     } break;
    case lostFailed:
     {
      //wrong login, so adl_callHangup() or go back to lostFirst
     }
   }
 }

bool gsm_DataHandler(u16 DataLen, u8 *Data)
 {
  int i;
  for (i=0; i<DataLen; i++)
   {
    char c=(char)(Data[i]);
    switch (LoginState)
     {
      case lostLogin:
       {
        if (c=='\n')
         {
          LoginBuffer[LoginBufferUsed]=0;
          if (wm_strcmp(LoginBuffer, "user")==0)
           {
            adl_fcmSendData(gsmFcmHandle, "Password:\r\n", 11);
            LoginBufferUsed=0;
            LoginState=lostPassword;
           }
          else
            LoginState=lostFailed;
         }
        else
         {
          LoginBuffer[LoginBufferUsed++]=c;
          if (LoginBufferUsed>=19)
           {
            LoginState=lostFailed; //name too long
           }
         }
       } break; //lostLogin
      //same for lostPassword, but go to lostLoggedIn
     } //switch
   } //for over Data[]
  return true;
 }

You’ll need to clean it up a bit, but I guess you’ve got more than you wanted already. It’s really just C programming, nothing Wavecom specific.


#7

That’s great, Master :stuck_out_tongue:. Thank you very much ^_^.