blob: df063c299f90179dd32fb3b9d52c5db477ade5b1 [file] [log] [blame]
/******************************************************************************
*(C) Copyright 2011 Marvell International Ltd.
* All Rights Reserved
******************************************************************************/
/*--------------------------------------------------------------------------------------------------------------------
* -------------------------------------------------------------------------------------------------------------------
*
* Filename: tcp_state_machine.c
*
* Description: The APIs to handle TCP state machine.
*
* History:
* Aug, 13 2012 - Haili Wang(hlw@marvell.com) Creation of file
*
* Notes:
*
******************************************************************************/
#include "utlStateMachine.h"
#include "tcp_state_machine.h"
#include "diag_state_machine.h"
#include "tcp_api.h"
#include "diag_config.h"
#include "pxa_dbg.h"
#define STATE_START utlDEFINE_STATE_ID(1)
#define STATE_PREPARING utlDEFINE_STATE_ID(2)
#define STATE_ACCEPTING utlDEFINE_STATE_ID(3)
#define STATE_ACCEPTED utlDEFINE_STATE_ID(4)
static utlStateMachine_P state_machine_p;
static utlRelativeTime_T preparing_timeout = {1,0}; // 100ms
static unsigned int preparing_retries = 20;
static int disconnecting = 1; //todo, is it a better machnism or not ?
utlEVENT_HANDLER(TCPReset, arg_p, va_arg_p)
{
F_ENTER();
return utlSET_STATE(utlSTATE_ID_BOOT);
}
utlEVENT_HANDLER(TCPStart, arg_p, va_arg_p)
{
F_ENTER();
return utlSET_STATE(STATE_START);
}
utlEVENT_HANDLER(TCPPrepareRetry, arg_p, va_arg_p)
{
F_ENTER();
if(prepareListenSocket() < 0 )
{
return utlSET_STATE(STATE_PREPARING);
}
else
{
return utlEVENT(EVENT_PREPARED);
}
}
utlEVENT_HANDLER(TCPPrepareGiveUp, arg_p, va_arg_p)
{
F_ENTER();
return utlSET_STATE(utlSTATE_ID_BOOT);
}
utlEVENT_HANDLER(TCPPrepared, arg_p, va_arg_p)
{
return utlSET_STATE(STATE_ACCEPTING);
}
utlEVENT_HANDLER(TCPAccepted, arg_p, va_arg_p)
{
return utlSET_STATE(STATE_ACCEPTED);
}
utlEVENT_HANDLER(TCPDisconnected, arg_p, va_arg_p)
{
return utlSET_STATE(STATE_START);
}
utlEVENT_HANDLER(TCPEventDefault, arg_p, va_arg_p)
{
//do nothing if the event is not for such state.
return utlSUCCESS;
}
/*------------------------------------*/
utlSTATE_CHANGE_HANDLER(TCPEnterBoot, arg_p)
{
return utlSUCCESS;
}
utlSTATE_CHANGE_HANDLER(TCPEnterStart, arg_p)
{
configInterface();
createListenSocket();
return utlSET_STATE(STATE_PREPARING);
}
utlSTATE_CHANGE_HANDLER(TCPEnterPreparing, arg_p)
{
return utlSUCCESS;
}
utlSTATE_CHANGE_HANDLER(TCPEnterAccepting, arg_p)
{
return utlSUCCESS;
}
utlSTATE_CHANGE_HANDLER(TCPLeaveAccepting, arg_p)
{
//close listen socket since we support only one client
closeListenSocket();
return utlSUCCESS;
}
utlSTATE_CHANGE_HANDLER(TCPEnterAccepted, arg_p)
{
LogcatTaskResume(diagTCPConnection);
disconnecting = 0;
DiagSwitch();
return utlSUCCESS;
}
utlSTATE_CHANGE_HANDLER(TCPLeaveAccepted, arg_p)
{
disconnecting = 1;
DiagSwitch();
closeDataSocket();
LogcatTaskSuspend(diagTCPConnection);
return utlSUCCESS;
}
static utlStateMachineEvent_T boot_events[] = {
utlDEFINE_EVENT_HANDLER_RESET(TCPReset),
utlDEFINE_EVENT_HANDLER_START(TCPStart),
utlDEFINE_EVENT_HANDLER_DEFAULT(TCPEventDefault),
utlDEFINE_EVENT_HANDLER_NULL() };
static utlStateMachineEvent_T start_events[] = {
utlDEFINE_EVENT_HANDLER_DEFAULT(TCPEventDefault),
utlDEFINE_EVENT_HANDLER_NULL() };
static utlStateMachineEvent_T preparing_events[] = {
utlDEFINE_EVENT_HANDLER_RETRY(TCPPrepareRetry),
utlDEFINE_EVENT_HANDLER_GIVE_UP(TCPPrepareGiveUp),
utlDEFINE_EVENT_HANDLER(EVENT_PREPARED, "TCP SOCKET PREPARED", TCPPrepared),
utlDEFINE_EVENT_HANDLER_DEFAULT(TCPEventDefault),
utlDEFINE_EVENT_HANDLER_NULL() };
static utlStateMachineEvent_T accpeting_events[] = {
utlDEFINE_EVENT_HANDLER(EVENT_ACCEPTED, "TCP SOCKET ACCEPTED", TCPAccepted),
utlDEFINE_EVENT_HANDLER_DEFAULT(TCPEventDefault),
utlDEFINE_EVENT_HANDLER_NULL() };
static utlStateMachineEvent_T accpeted_events[] = {
utlDEFINE_EVENT_HANDLER(EVENT_DISCONNECTED, "TCP SOCKET DISCONNECTED", TCPDisconnected),
utlDEFINE_EVENT_HANDLER_DEFAULT(TCPEventDefault),
utlDEFINE_EVENT_HANDLER_NULL() };
static utlStateMachineState_T tcp_states[] ={
utlDEFINE_STATE_BOOT( boot_events, NULL, NULL, TCPEnterBoot, NULL),
utlDEFINE_STATE(STATE_START, "TCP Start", start_events, NULL, NULL, TCPEnterStart, NULL),
utlDEFINE_STATE(STATE_PREPARING, "TCP Preparing", preparing_events, &preparing_timeout, &preparing_retries, TCPEnterPreparing, NULL),
utlDEFINE_STATE(STATE_ACCEPTING, "TCP Accepting", accpeting_events, NULL, NULL, TCPEnterAccepting, TCPLeaveAccepting),
utlDEFINE_STATE(STATE_ACCEPTED, "TCP Accepted", accpeted_events, NULL, NULL, TCPEnterAccepted, TCPLeaveAccepted),
utlDEFINE_STATE_NULL()};
int InitTCPMachine(void)
{
F_ENTER();
state_machine_p = utlOpenStateMachine("TCP Machine", 0, tcp_states, NULL);
F_LEAVE();
if(state_machine_p)
return 0;
else
return -1;
}
int StartTCPMachine(void)
{
if(state_machine_p)
{
return utlStateMachineEvent(state_machine_p, utlSTATE_EVENT_ID_START, NULL);
}
return -1;
}
int StopTCPMachine(void)
{
if(state_machine_p)
{
return utlSetStateMachineState(state_machine_p, utlSTATE_ID_BOOT, NULL);
}
return -1;
}
int TCPAccept(void)
{
if(state_machine_p)
{
return utlStateMachineEvent(state_machine_p, EVENT_ACCEPTED, NULL);
}
return -1;
}
int TCPDisconnect(void)
{
if(state_machine_p)
{
return utlStateMachineEvent(state_machine_p, EVENT_DISCONNECTED, NULL);
}
return -1;
}
int TCPIsConnected(void)
{
if(state_machine_p)
{
return !disconnecting;
}
return 0;
}