/******************************************************************************/
// @copyright   Copyright Notification
//   No part may be reproduced except as authorized by written permission.
//   The copyright and the foregoing restriction extend to reproduction in all media.
//   Trademark 2010, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC).
//   All rights reserved.
// @version: IWD_10wk37
// $Date: 2010-09-15 17:58:51 +0200 (Wed, 15 Sep 2010) $
// $Rev: 3904 $
/******************************************************************************/
//------------------------------------------------------------------------------
//* History:
//*   R5-096657   Added SMS command DELETE_MESSAGE_WITHFLAG
//------------------------------------------------------------------------------

module MTC_UpperTester {
  import from CommonDefs all;
  import from MTC_Component all;
  import from UpperTesterDefs all;

  //--------------------------------------------------------------------------
  // local type definitions:
  type enumerated UT_Cnf_State_Type { /* @status    APPROVED */
    NO_CNF_REQUIRED, CNF_EUTRA, CNF_UTRAN, CNF_GERAN, CNF_CDMA2000
  };
  type record UT_Ctrl_Type { /* @status    APPROVED */
    UT_Cnf_State_Type Cnf_State,
    boolean UE_SwitchedOn
  };

  //=============================================================================
  // TEMPLATES
  //-----------------------------------------------------------------------------

  const charstring      tsc_AT_ResultOK := "<CR><LF>OK<CR><LF>";

  template UT_COMMON_CNF car_UT_COMMON_CNF :=
  { /* @status    APPROVED */
    Result          := ?,  // result is a mandatory field
    ResultString    := *
  };

  template UT_COMMON_CMD car_UT_ReqAny :=
  { /* @status    APPROVED */
    Cmd := ?,
    CnfReq := ?,
    ParameterList := *
  };

  template (value) Ut_System_Cmd_Type cs_AT_Cmd(charstring p_AtCmd) :=
  { /* @status    APPROVED */
    AT := p_AtCmd
  };

  template (value) Ut_System_Cmd_Type cs_MMI_Cmd(charstring p_MmiCmd,
                                                 template (omit) Ut_ParameterList_Type p_ParamList) :=
  { /* @status    APPROVED */
    MMI := {
      Cmd := p_MmiCmd,
      ParameterList := p_ParamList
    }
  };

  template (value) Ut_System_Cmd_Type cs_MMI_COMBINED_ATTACH      := cs_MMI_Cmd("PRE_CONFIGURE_FOR_COMBINED_EPS_IMSI_ATTACH", omit); /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_EPS_ATTACH           := cs_MMI_Cmd("PRE_CONFIGURE_FOR_EPS_ATTACH", omit);               /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_DISABLE_EPS          := cs_MMI_Cmd("DISABLE_EPS_CAPABILITY", omit);   /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_POWER_OFF            := cs_MMI_Cmd("POWER_OFF", omit);   /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_POWER_ON             := cs_MMI_Cmd("POWER_ON", omit);    /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_SWITCH_OFF           := cs_MMI_Cmd("SWITCH_OFF", omit);  /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_SWITCH_ON            := cs_MMI_Cmd("SWITCH_ON", omit);   /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_INSERT_USIM_NoParams := cs_MMI_Cmd("INSERT_USIM", omit); /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_INSERT_USIM (template (value) Ut_ParameterList_Type p_ParamList) :=
    cs_MMI_Cmd("INSERT_USIM", p_ParamList);                                                           /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_REMOVE_USIM          := cs_MMI_Cmd("REMOVE_USIM", omit); /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_CS_CALL (charstring p_Dial) :=
    cs_AT_Cmd("ATD"&p_Dial&",<CR>");                                                                  /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_ANSWER_CS_CALL        := cs_AT_Cmd("ATA<CR>");                                                                  /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_DEFINE_EPS_QOS (charstring p_QoS) :=
    cs_AT_Cmd("AT+CGEQOS="& p_QoS &"<CR>");                                                           /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_DEFINE_TFT  (charstring p_TFT) :=
    cs_AT_Cmd("AT+CGTFT="& p_TFT &"<CR>");                                                            /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_REQUEST_DED_BEARER  (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+CGDSCONT="& p_ParamList[0].Value& "," & p_ParamList[1].Value & "<CR>");             /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_ACTIVATEBEARER  (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+CGACT=1,"& p_ParamList[0].Value &"<CR>");                                           /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_DEACTIVATEBEARER  (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+CGACT=0,"& p_ParamList[0].Value &"<CR>");                                           /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_MODIFYBEARER  (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+CGCMOD="& p_ParamList[0].Value &"<CR>");  // @sic R5s100470 sic@                                         /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_CHECK_PLMN (template (omit) Ut_ParameterList_Type p_ParamList) :=
    cs_MMI_Cmd("CHECK_PLMN", p_ParamList);                                                            /* @status    APPROVED */

  template (value) Ut_System_Cmd_Type cs_MMI_SET_PLMN_MANUAL := cs_MMI_Cmd("PLMN_MANUAL", omit);           /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_PLMN_MANUAL (template (omit) Ut_ParameterList_Type p_ParamList) :=
    cs_MMI_Cmd("SELECT_PLMN", p_ParamList);                                                           /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_PLMN_AUTOMATIC  := cs_MMI_Cmd("PLMN_AUTOMATIC", omit);   /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_REQUEST_PDPCONTEXT (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+CGDCONT=" & p_ParamList[0].Value &"<CR>");                                          /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_REQUEST_ATTACH := cs_AT_Cmd("AT+CGATT=1<CR>");            /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_REQUEST_DETACH := cs_AT_Cmd("AT+CGATT=0<CR>");            /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_DELETE_MESSAGE_DELFLAG  (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+CMGD="& p_ParamList[0].Value& "," & p_ParamList[1].Value & "<CR>");                 /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_SELECT_MESSAGE_SERVICE  (charstring p_Service) :=
    cs_AT_Cmd("AT+CSMS="& p_Service &"<CR>");                                                         /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_SET_PREFERRED_STORAGE  (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+CPMS="& p_ParamList[0].Value& "," & p_ParamList[1].Value & p_ParamList[2].Value & "<CR>"); /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_MESSAGE_FORMAT  (charstring p_Mode) :=
    cs_AT_Cmd("AT+CMGF="& p_Mode & "<CR>");                                                           /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_SELECT_CHARACTER_SET  (charstring p_Chset) :=
    cs_AT_Cmd("AT+CSCS="& p_Chset & "<CR>");                                                          /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_SERVICE_CENTRE_ADDRESS  (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+CSCA="& p_ParamList[0].Value& "," & p_ParamList[1].Value & "<CR>");                 /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_MESSAGE_WRITE_TEXTMODE  (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+CMGW="& p_ParamList[0].Value& "," & p_ParamList[1].Value & "<CR>" & p_ParamList[2].Value & "<SUB><CR>"); /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_SEND_STORED_ONEMESSAGE  (charstring p_Index) :=
    cs_AT_Cmd("AT+CMSS="& p_Index &"<CR>");                                                           /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_SET_TEXTMODE_PARAMETERS  (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+CSMP="& p_ParamList[0].Value &"<CR>");                                              /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_MMI_CHECK_MESSAGE_DISPLAYED (Ut_ParameterList_Type p_ParamList) :=
    cs_MMI_Cmd("CHECK_SMS_LENGTH_CONTENTS", p_ParamList);                                             /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_CHECK_CLOCK :=
    cs_AT_Cmd("AT+CCLK?<CR>");                                                                        /* @status    APPROVED */
  template (value) Ut_System_Cmd_Type cs_AT_CHECK_OPERATOR_NAME (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+COPS=3,"& p_ParamList[0].Value &";+COPS?<CR>");                                     /* @status    APPROVED */

  template (value) Ut_System_Cmd_Type cs_AT_QOS_PROFILE_REQUESTED  (Ut_ParameterList_Type p_ParamList) :=
    cs_AT_Cmd("AT+CGEQREQ="& p_ParamList[0].Value& "," & p_ParamList[1].Value &"<CR>");               /* @status    APPROVED */
  template (value) UT_SYSTEM_REQ cas_UT_SYSTEM_REQ(template (value) Ut_System_Cmd_Type p_ATorMMI_Cmd,
                                                   boolean p_CnfRequired) :=
  { /* @status    APPROVED */
    Cmd := p_ATorMMI_Cmd,
    CnfRequired := p_CnfRequired
  };

  // =============================================================================
  // local functions:
  /*
   * @desc      handles the commands being sent by the PTCs (UT_COMMON_CMD);
   *            the commands may either be mapped to AT or to MMI commands
   * @param     p_UT_Ctrl_ByRef     (by reference)
   * @param     p_UT_Req
   * @param     p_NewCnfState
   * @status    APPROVED
   */
  function fl_UT_HandleCmd(inout UT_Ctrl_Type p_UT_Ctrl_ByRef,
                           UT_COMMON_CMD p_UT_Req,
                           UT_Cnf_State_Type p_NewCnfState) runs on MTC
  {
    var template (omit) Ut_ParameterList_Type v_ParamList := p_UT_Req.ParameterList;
    var boolean v_UeToBeSwitchedOn := p_UT_Ctrl_ByRef.UE_SwitchedOn;
    var boolean v_CnfRequired := false;
    var template (value) Ut_System_Cmd_Type v_SystemCmd;

    if (p_UT_Ctrl_ByRef.Cnf_State != NO_CNF_REQUIRED) {     // check that there is no AT or MMI command is ongoing
      FatalError (__FILE__, __LINE__, "unexpected Upper Tester command");
    }
    if (p_UT_Req.CnfReq == CNF_REQUIRED) {
      p_UT_Ctrl_ByRef.Cnf_State := p_NewCnfState;
      v_CnfRequired := true;
    }
    select (p_UT_Req.Cmd) {
      case (POWER_OFF) {
        v_UeToBeSwitchedOn := false;
        v_SystemCmd := cs_MMI_POWER_OFF;
      }
      case (POWER_ON) {
        v_UeToBeSwitchedOn := true;
        v_SystemCmd := cs_MMI_POWER_ON;
      }
      case (SWITCH_OFF) {
        v_UeToBeSwitchedOn := false;
        v_SystemCmd := cs_MMI_SWITCH_OFF;
      }
      case (SWITCH_ON) {
        v_UeToBeSwitchedOn := true;
        v_SystemCmd := cs_MMI_SWITCH_ON;
      }
      case (CONFIGURE_COMBINED_ATTACH) {
        v_SystemCmd := cs_MMI_COMBINED_ATTACH;
      }
      case (CONFIGURE_EPS_ATTACH) {
        v_SystemCmd := cs_MMI_EPS_ATTACH;
      }
      case (DISABLE_EPS) {
        v_SystemCmd := cs_MMI_DISABLE_EPS;
      }
      case (INSERT_USIM) {
        if (isvalue(v_ParamList)) {
          v_SystemCmd := cs_MMI_INSERT_USIM(v_ParamList);
        } else {
          v_SystemCmd := cs_MMI_INSERT_USIM_NoParams;
        }
      }
      case (REMOVE_USIM) {
        v_SystemCmd := cs_MMI_REMOVE_USIM;
      }
      case (REQUEST_CS_CALL) {
        v_SystemCmd := cs_AT_CS_CALL (valueof(v_ParamList[0].Value));
      }
      case (CHECK_PLMN)  {
        v_SystemCmd := cs_MMI_CHECK_PLMN (v_ParamList);
      }
      case (DEFINE_EPS_QOS)  {
        v_SystemCmd := cs_AT_DEFINE_EPS_QOS (valueof(v_ParamList[0].Value));
      }
      case (DEFINE_TFT)  {
        v_SystemCmd := cs_AT_DEFINE_TFT (valueof(v_ParamList[0].Value));
      }
      case (REQUEST_DED_BEARER)  {
        v_SystemCmd := cs_AT_REQUEST_DED_BEARER (valueof(v_ParamList));
      }
      case (ACTIVATE_BEARER)  {
        v_SystemCmd := cs_AT_ACTIVATEBEARER (valueof(v_ParamList));
      }
      case (SELECT_PLMN)  {
        v_SystemCmd := cs_MMI_PLMN_MANUAL (v_ParamList);
      }
      case (PLMN_AUTOMATIC)  {
        v_SystemCmd := cs_MMI_PLMN_AUTOMATIC;
      }
      case (PLMN_MANUAL) {
        v_SystemCmd := cs_MMI_SET_PLMN_MANUAL;
      }
      case (REQUEST_PDPCONTEXT)  {
        v_SystemCmd := cs_AT_REQUEST_PDPCONTEXT(valueof(v_ParamList));
      }
      case (DEACTIVATE_BEARER)  {
        v_SystemCmd := cs_AT_DEACTIVATEBEARER(valueof(v_ParamList));
      }
      case (MODIFY_BEARER)  {
        v_SystemCmd := cs_AT_MODIFYBEARER(valueof(v_ParamList));
      }
      case (ATTACH)  {
        v_SystemCmd := cs_AT_REQUEST_ATTACH;
      }
      case (DETACH)  {
        v_SystemCmd := cs_AT_REQUEST_DETACH;
      }
      case (DELETE_MESSAGE_WITHFLAG)  {
        v_SystemCmd := cs_AT_DELETE_MESSAGE_DELFLAG (valueof(v_ParamList));
      }
      case (SELECT_MESSAGE_SERVICE)  {
        v_SystemCmd := cs_AT_SELECT_MESSAGE_SERVICE (valueof(v_ParamList[0].Value));
      }
      case (SET_PREFERRED_STORAGE)  {
        v_SystemCmd := cs_AT_SET_PREFERRED_STORAGE (valueof(v_ParamList));
      }
      case (MESSAGE_FORMAT)  {
        v_SystemCmd := cs_AT_MESSAGE_FORMAT (valueof(v_ParamList[0].Value));
      }
      case (SELECT_CHARACTER_SET)  {
        v_SystemCmd := cs_AT_SELECT_CHARACTER_SET (valueof(v_ParamList[0].Value));
      }
      case (SERVICE_CENTRE_ADDRESS)  {
        v_SystemCmd := cs_AT_SERVICE_CENTRE_ADDRESS (valueof(v_ParamList));
      }
      case (WRITE_MESSAGE_TOMEMORY_TEXTMODE)  {
        v_SystemCmd := cs_AT_MESSAGE_WRITE_TEXTMODE (valueof(v_ParamList));
      }
      case (SEND_STORED_MESSAGE_ONE)  {
        v_SystemCmd := cs_AT_SEND_STORED_ONEMESSAGE (valueof(v_ParamList[0].Value));
      }
      case (SET_TEXTMODE_PARAMETERS)  {
        v_SystemCmd := cs_AT_SET_TEXTMODE_PARAMETERS (valueof(v_ParamList));
      }
      case (CHECK_MESSAGE_DISPLAYED)  {
        v_SystemCmd := cs_MMI_CHECK_MESSAGE_DISPLAYED (valueof(v_ParamList));
      }
      case (DEFINE_QOS)  {
        v_SystemCmd := cs_AT_QOS_PROFILE_REQUESTED (valueof(v_ParamList));
      }
      case (CHECK_CLOCK)  {
        v_SystemCmd := cs_AT_CHECK_CLOCK;
      }
      case (CHECK_OPERATOR_NAME)  {
        v_SystemCmd := cs_AT_CHECK_OPERATOR_NAME (valueof(v_ParamList));
      }
      case (ANSWER_CS_CALL)  {
        v_SystemCmd := cs_AT_ANSWER_CS_CALL;
      }
    }
    if (p_UT_Ctrl_ByRef.UE_SwitchedOn != v_UeToBeSwitchedOn) {            // UE needs to be switched on or off
      p_UT_Ctrl_ByRef.UE_SwitchedOn := v_UeToBeSwitchedOn;
    }
    Ut.send(cas_UT_SYSTEM_REQ(v_SystemCmd, v_CnfRequired));
  }
  //----------------------------------------------------------------------------
  /*
   * @desc      send confirmation to the respective PTC
   * @param     p_Port
   * @param     p_UT_Cnf
   * @status    APPROVED
   */
  function fl_UT_SendCnf(UT_MTC_PTC_PORT p_Port,
                         template (value) UT_COMMON_CNF p_UT_Cnf)
  {
    // note: function is needed since ports can be parameters of a function but not be local variables
    p_Port.send(p_UT_Cnf);
  }
  //----------------------------------------------------------------------------
  /*
   * @desc      deal with confirmations from the upper tester
   * @param     p_UT_Ctrl_ByRef     (by reference)
   * @param     p_UT_Cnf
   * @status    APPROVED
   */
  function fl_UT_HandleCnf(inout UT_Ctrl_Type p_UT_Ctrl_ByRef,
                           template (value) UT_COMMON_CNF p_UT_Cnf) runs on MTC
  { /* R5-104796 change 12: @sic CDMA2000 added sic@ */
    if (p_UT_Ctrl_ByRef.Cnf_State == CNF_EUTRA) {
      fl_UT_SendCnf(E_Ut, p_UT_Cnf);

    } else if (p_UT_Ctrl_ByRef.Cnf_State == CNF_UTRAN) {
      fl_UT_SendCnf(U_Ut, p_UT_Cnf);

    } else if (p_UT_Ctrl_ByRef.Cnf_State == CNF_GERAN) {
      fl_UT_SendCnf(G_Ut, p_UT_Cnf);

    } else if (p_UT_Ctrl_ByRef.Cnf_State == CNF_CDMA2000) {
      fl_UT_SendCnf(CDMA2000_Ut, p_UT_Cnf);

    } else { // p_UT_Ctrl_ByRef.Cnf_State == NO_CNF_REQUIRED => just discard the CNF
      return;
    }
    p_UT_Ctrl_ByRef.Cnf_State := NO_CNF_REQUIRED;
  }
  //=============================================================================
  /*
   * @desc      initialise upper tester
   * @return    UT_Ctrl_Type
   * @status    APPROVED
   */
  function f_UT_Ctrl_Init() return UT_Ctrl_Type
  {
    var UT_Ctrl_Type v_UT_Ctrl;
    v_UT_Ctrl.Cnf_State := NO_CNF_REQUIRED;
    v_UT_Ctrl.UE_SwitchedOn := false;
    return v_UT_Ctrl;
  }
  //----------------------------------------------------------------------------
  /*
   * @desc      cause the UE to be switched off at the beginning of a teat case
   * @status    APPROVED
   */
  function f_UT_InitialPowerOffUE() runs on MTC
  {
    var boolean v_CnfRequired := true;
    Ut.send(cas_UT_SYSTEM_REQ(cs_MMI_POWER_OFF, v_CnfRequired));
    Ut.receive(car_UT_COMMON_CNF);
  }
  //=============================================================================
  /*
   * @desc      message handler for the upper tester
   * @param     p_UT_Ctrl_ByRef     (by reference)
   * @status    APPROVED
   */
  altstep a_UpperTester(inout UT_Ctrl_Type p_UT_Ctrl_ByRef) runs on MTC
  {
    // p_UT_Ctrl_ByRef needs to be inout to store state information
    var UT_COMMON_CMD v_UT_Req;
    var UT_COMMON_CNF v_UT_Cnf;

    [] E_Ut.receive(car_UT_ReqAny)      -> value v_UT_Req
      {
        fl_UT_HandleCmd(p_UT_Ctrl_ByRef, v_UT_Req, CNF_EUTRA);
      }
    [] U_Ut.receive(car_UT_ReqAny)      -> value v_UT_Req
      {
        fl_UT_HandleCmd(p_UT_Ctrl_ByRef, v_UT_Req, CNF_UTRAN);
      }
    [] G_Ut.receive(car_UT_ReqAny)      -> value v_UT_Req
      {
        fl_UT_HandleCmd(p_UT_Ctrl_ByRef, v_UT_Req, CNF_GERAN);
      }
    [] Ut.receive (car_UT_COMMON_CNF)    -> value v_UT_Cnf
      {
        if (v_UT_Cnf.Result == false) { // If not received a successful confirmation, stop everything
          FatalError (__FILE__, __LINE__, "AT/MMI Command failed");

        } else {
          fl_UT_HandleCnf(p_UT_Ctrl_ByRef, v_UT_Cnf);
        }
      }
  }
}
