| /* ------------------------------------------------------------------ |
| * Copyright (C) 1998-2009 PacketVideo |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| * express or implied. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * ------------------------------------------------------------------- |
| */ |
| // ---------------------------------------------------------------------- |
| // |
| // This Software is an original work of authorship of PacketVideo Corporation. |
| // Portions of the Software were developed in collaboration with NTT DoCoMo, |
| // Inc. or were derived from the public domain or materials licensed from |
| // third parties. Title and ownership, including all intellectual property |
| // rights in and to the Software shall remain with PacketVideo Corporation |
| // and NTT DoCoMo, Inc. |
| // |
| // ----------------------------------------------------------------------- |
| /************************************************************************/ |
| /* file name : semsd.h */ |
| /* file contents : Master Slave Determination Signalling Entity */ |
| /* : Management Header */ |
| /* draw : '96.11.11 */ |
| /*----------------------------------------------------------------------*/ |
| /* amendment : */ |
| /* Copyright (C) 1996 NTT DoCoMo */ |
| /************************************************************************/ |
| #ifndef _SEMSD_ |
| #define _SEMSD_ |
| |
| #include "oscl_base.h" |
| #include "oscl_rand.h" |
| #include "oscl_tickcount.h" |
| #include "oscl_timer.h" |
| #include "sebase.h" |
| #include "h245def.h" |
| #include "h245inf.h" |
| #include "semsgque.h" |
| |
| #define TWO_24 (1<<24) |
| #define TWO_23 (1<<23) |
| #define MSD_MAX_RETRIES 100 |
| |
| enum MSDStatus { MSD_INDETERMINATE = 0, MSD_MASTER = 1, MSD_SLAVE = 2 }; |
| enum MSDErrCode |
| { |
| MSD_ERROR_CODE_A = 0, // no response from remove MSD |
| MSD_ERROR_CODE_B = 1, // remote MSD see no response from local MSD |
| MSD_ERROR_CODE_C = 2, // inappropriate message |
| MSD_ERROR_CODE_D = 3, // inappropriate message |
| MSD_ERROR_CODE_E = 4, // inconsistent field value |
| MSD_ERROR_CODE_F = 5 // max number of retries reached |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////// |
| class MSDObserver |
| { |
| public: |
| virtual ~MSDObserver() {} |
| virtual void MSDDetermineConfirm(MSDStatus type) = 0; |
| virtual void MSDDetermineIndication(MSDStatus type) = 0; |
| virtual void MSDRejectIndication() = 0; |
| virtual void MSDErrorIndication(MSDErrCode errCode) = 0; |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////// |
| class MSD : public SEBase, public OsclTimerObserver |
| { |
| private: |
| enum MSDState { IDLE, OUTGOING_AWAITING_RESPONSE, INCOMING_AWAITING_RESPONSE }; // states |
| |
| public: |
| MSD() : |
| Observer(NULL), |
| TerminalType(128), |
| State(IDLE), |
| Status(MSD_INDETERMINATE), |
| StatusDeterminationNumber(0), |
| RetryCnt(0) |
| { |
| // seed the random number generator |
| RandGen.Seed(OsclTickCount::TickCount()); |
| // calcuate initial status determination number |
| NewStatusDeterminationNumber(); |
| } |
| |
| virtual ~MSD() {} |
| |
| void Reset() |
| { |
| Print("Reset MSD\n"); |
| State = IDLE; |
| Status = MSD_INDETERMINATE; |
| RetryCnt = 0; |
| // calcuate new status determination number |
| NewStatusDeterminationNumber(); |
| ResetTimer(); |
| } |
| |
| void SetObserver(MSDObserver *observer) |
| { |
| Observer = observer; |
| } |
| |
| void SetTerminalType(uint8 ttype) |
| { |
| TerminalType = ttype; |
| } |
| |
| void DetermineRequest() |
| { |
| Print("Received MSD Determine Request\n"); |
| switch (GetState()) |
| { |
| case IDLE: |
| Idle(); |
| break; |
| case OUTGOING_AWAITING_RESPONSE: |
| case INCOMING_AWAITING_RESPONSE: |
| default: |
| break; |
| } |
| } |
| |
| void Handler(PS_MasterSlaveDetermination msd) |
| { |
| Print("Received MSD\n"); |
| switch (GetState()) |
| { |
| case IDLE: |
| Idle(msd); |
| break; |
| case OUTGOING_AWAITING_RESPONSE: |
| OutgoingAwaitingResponse(msd); |
| break; |
| case INCOMING_AWAITING_RESPONSE: |
| IncomingAwaitingResponse(msd); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| void Handler(PS_MasterSlaveDeterminationAck msda) |
| { |
| Print("Received MSDAck\n"); |
| switch (GetState()) |
| { |
| case IDLE: |
| break; |
| case OUTGOING_AWAITING_RESPONSE: |
| OutgoingAwaitingResponse(msda); |
| break; |
| case INCOMING_AWAITING_RESPONSE: |
| IncomingAwaitingResponse(msda); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| void Handler(PS_MasterSlaveDeterminationReject msdr) |
| { |
| Print("Received MSDReject\n"); |
| switch (GetState()) |
| { |
| case IDLE: |
| break; |
| case OUTGOING_AWAITING_RESPONSE: |
| OutgoingAwaitingResponse(msdr); |
| break; |
| case INCOMING_AWAITING_RESPONSE: |
| IncomingAwaitingResponse(msdr); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| void Handler(PS_MasterSlaveDeterminationRelease msdr) |
| { |
| Print("Received MSDRelease\n"); |
| switch (GetState()) |
| { |
| case IDLE: |
| break; |
| case OUTGOING_AWAITING_RESPONSE: |
| OutgoingAwaitingResponse(msdr); |
| break; |
| case INCOMING_AWAITING_RESPONSE: |
| IncomingAwaitingResponse(msdr); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| void HandlerTimeout() |
| { |
| Print("Received MSD Timeout\n"); |
| switch (GetState()) |
| { |
| case IDLE: |
| break; |
| case OUTGOING_AWAITING_RESPONSE: |
| OutgoingAwaitingResponseTimeout(); |
| break; |
| case INCOMING_AWAITING_RESPONSE: |
| IncomingAwaitingResponseTimeout(); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| void TimeoutOccurred(int32 timerID, int32 timeoutInfo) |
| { |
| Print(" MSD::TimeoutOccurred"); |
| |
| OSCL_UNUSED_ARG(timerID); |
| OSCL_UNUSED_ARG(timeoutInfo); |
| HandlerTimeout(); |
| } |
| |
| MSDStatus GetStatus() |
| { |
| if (Status == MSD_INDETERMINATE) Print(" Status == INDETERMINATE\n"); |
| else if (Status == MSD_MASTER) Print(" Status == MASTER\n"); |
| else if (Status == MSD_SLAVE) Print(" Status == SLAVE\n"); |
| |
| return Status; |
| } |
| |
| private: |
| MSD(const MSD&); |
| |
| void SetStatus(MSDStatus status) |
| { |
| Status = status; |
| |
| if (Status == MSD_INDETERMINATE) Print(" Status -> INDETERMINATE\n"); |
| else if (Status == MSD_MASTER) Print(" Status -> MASTER\n"); |
| else if (Status == MSD_SLAVE) Print(" Status -> SLAVE\n"); |
| } |
| |
| void SetState(MSDState state) |
| { |
| State = state; |
| |
| if (State == IDLE) Print(" State -> IDLE\n"); |
| else if (State == OUTGOING_AWAITING_RESPONSE) Print(" State -> OUTGOING_AWAITING_RESPONSE\n"); |
| else if (State == INCOMING_AWAITING_RESPONSE) Print(" State -> INCOMING_AWAITING_RESPONSE\n"); |
| } |
| |
| MSDState GetState() |
| { |
| if (State == IDLE) Print(" State == IDLE\n"); |
| else if (State == OUTGOING_AWAITING_RESPONSE) Print(" State == OUTGOING_AWAITING_RESPONSE\n"); |
| else if (State == INCOMING_AWAITING_RESPONSE) Print(" State == INCOMING_AWAITING_RESPONSE\n"); |
| |
| return State; |
| } |
| |
| // Handles Determine.Request when in IDLE state |
| void Idle() |
| { |
| RetryCnt = 1; |
| SetTimer(); |
| SetState(OUTGOING_AWAITING_RESPONSE); |
| SendMSD(); |
| } |
| |
| void Idle(PS_MasterSlaveDetermination msd) |
| { |
| DetermineStatus(msd); |
| if (GetStatus() == MSD_INDETERMINATE) |
| { |
| SendMSDReject(); |
| } |
| else |
| { |
| SetTimer(); |
| SetState(INCOMING_AWAITING_RESPONSE); |
| SendMSDAck(); |
| if (Observer) Observer->MSDDetermineIndication(Status); |
| } |
| } |
| |
| void OutgoingAwaitingResponse(PS_MasterSlaveDeterminationAck msda) |
| { |
| ResetTimer(); |
| SetStatus(((msda->decision.index == 0) ? MSD_MASTER : MSD_SLAVE)); |
| SetState(IDLE); |
| SendMSDAck(); |
| if (Observer) Observer->MSDDetermineConfirm(Status); |
| } |
| |
| void OutgoingAwaitingResponse(PS_MasterSlaveDetermination msd) |
| { |
| ResetTimer(); |
| DetermineStatus(msd); |
| if (GetStatus() == MSD_INDETERMINATE) |
| { |
| if (RetryCnt >= MSD_MAX_RETRIES) |
| { |
| SetState(IDLE); |
| if (Observer) |
| { |
| Observer->MSDErrorIndication(MSD_ERROR_CODE_F); |
| Observer->MSDRejectIndication(); |
| } |
| } |
| else |
| { |
| NewStatusDeterminationNumber(); |
| RetryCnt++; |
| SetTimer(); |
| SetState(OUTGOING_AWAITING_RESPONSE); |
| SendMSD(); |
| } |
| } |
| else |
| { |
| SetTimer(); |
| SetState(INCOMING_AWAITING_RESPONSE); |
| SendMSDAck(); |
| if (Observer) Observer->MSDDetermineIndication(Status); |
| } |
| } |
| |
| void OutgoingAwaitingResponse(PS_MasterSlaveDeterminationReject msdr) |
| { |
| OSCL_UNUSED_ARG(msdr); |
| ResetTimer(); |
| if (RetryCnt >= MSD_MAX_RETRIES) |
| { |
| SetState(IDLE); |
| if (Observer) |
| { |
| Observer->MSDErrorIndication(MSD_ERROR_CODE_F); |
| Observer->MSDRejectIndication(); |
| } |
| } |
| else |
| { |
| NewStatusDeterminationNumber(); |
| RetryCnt++; |
| SetTimer(); |
| SetState(OUTGOING_AWAITING_RESPONSE); |
| SendMSD(); |
| } |
| } |
| |
| void OutgoingAwaitingResponse(PS_MasterSlaveDeterminationRelease msdr) |
| { |
| OSCL_UNUSED_ARG(msdr); |
| ResetTimer(); |
| SetState(IDLE); |
| if (Observer) |
| { |
| Observer->MSDErrorIndication(MSD_ERROR_CODE_B); |
| Observer->MSDRejectIndication(); |
| } |
| } |
| |
| void OutgoingAwaitingResponseTimeout() |
| { |
| SendMSDRelease(); |
| SetState(IDLE); |
| if (Observer) |
| { |
| Observer->MSDErrorIndication(MSD_ERROR_CODE_A); |
| Observer->MSDRejectIndication(); |
| } |
| } |
| |
| void IncomingAwaitingResponse(PS_MasterSlaveDeterminationAck msda) |
| { |
| ResetTimer(); |
| if ((msda->decision.index == 0 && GetStatus() == MSD_MASTER) || |
| (msda->decision.index == 1 && GetStatus() == MSD_SLAVE)) |
| { |
| SetState(IDLE); |
| if (Observer) Observer->MSDDetermineConfirm(Status); |
| } |
| else |
| { |
| SetState(IDLE); |
| if (Observer) |
| { |
| Observer->MSDErrorIndication(MSD_ERROR_CODE_E); |
| Observer->MSDRejectIndication(); |
| } |
| } |
| } |
| |
| void IncomingAwaitingResponse(PS_MasterSlaveDetermination msd) |
| { |
| OSCL_UNUSED_ARG(msd); |
| ResetTimer(); |
| SetState(IDLE); |
| if (Observer) |
| { |
| Observer->MSDErrorIndication(MSD_ERROR_CODE_C); |
| Observer->MSDRejectIndication(); |
| } |
| } |
| |
| void IncomingAwaitingResponse(PS_MasterSlaveDeterminationReject msdr) |
| { |
| OSCL_UNUSED_ARG(msdr); |
| ResetTimer(); |
| SetState(IDLE); |
| if (Observer) |
| { |
| Observer->MSDErrorIndication(MSD_ERROR_CODE_D); |
| Observer->MSDRejectIndication(); |
| } |
| } |
| |
| void IncomingAwaitingResponse(PS_MasterSlaveDeterminationRelease msdr) |
| { |
| OSCL_UNUSED_ARG(msdr); |
| ResetTimer(); |
| SetState(IDLE); |
| if (Observer) |
| { |
| Observer->MSDErrorIndication(MSD_ERROR_CODE_B); |
| Observer->MSDRejectIndication(); |
| } |
| } |
| |
| void IncomingAwaitingResponseTimeout() |
| { |
| SetState(IDLE); |
| if (Observer) |
| { |
| Observer->MSDErrorIndication(MSD_ERROR_CODE_A); |
| Observer->MSDRejectIndication(); |
| } |
| } |
| |
| void DetermineStatus(PS_MasterSlaveDetermination msd) |
| { |
| Print(" My Terminal Type == %d, Incoming Terminal Type == %d\n", TerminalType, msd->terminalType); |
| Print(" My Status Det Num == 0x%08x, Incoming Status Det Num == 0x%08x\n", StatusDeterminationNumber, msd->statusDeterminationNumber); |
| |
| if (TerminalType != msd->terminalType) |
| { |
| SetStatus((TerminalType < msd->terminalType) ? MSD_SLAVE : MSD_MASTER); |
| } |
| else |
| { |
| uint32 diff = (msd->statusDeterminationNumber - StatusDeterminationNumber) % TWO_24; |
| if (diff == 0 || diff == TWO_23) SetStatus(MSD_INDETERMINATE); |
| else SetStatus((diff < TWO_23) ? MSD_MASTER : MSD_SLAVE); |
| } |
| } |
| |
| void SendMSD() |
| { |
| Print(" Sending MSD - Terminal Type == %d, Status Det Num == 0x%08x\n", TerminalType, StatusDeterminationNumber); |
| S_MasterSlaveDetermination masterSlaveDetermination ; |
| |
| masterSlaveDetermination.terminalType = TerminalType; |
| masterSlaveDetermination.statusDeterminationNumber = StatusDeterminationNumber; |
| |
| MessageSend(H245_MSG_REQ, MSGTYP_MSD, (uint8*)&masterSlaveDetermination); |
| } |
| |
| void SendMSDReject() |
| { |
| Print(" Sending MSDReject\n"); |
| S_MasterSlaveDeterminationReject masterSlaveDeterminationReject ; |
| |
| masterSlaveDeterminationReject.msdRejectCause.index = 0 ; |
| |
| MessageSend(H245_MSG_RPS, MSGTYP_MSD_RJT, (uint8*)&masterSlaveDeterminationReject) ; |
| } |
| |
| void SendMSDAck() |
| { |
| Print(" Sending MSDAck\n"); |
| S_MasterSlaveDeterminationAck masterSlaveDeterminationAck ; |
| |
| masterSlaveDeterminationAck.decision.index = (uint16)((Status == MSD_MASTER) ? 1 : 0); |
| |
| MessageSend(H245_MSG_RPS, MSGTYP_MSD_ACK, (uint8*)&masterSlaveDeterminationAck) ; |
| } |
| |
| void SendMSDRelease() |
| { |
| Print(" Sending MSDRelease\n"); |
| S_MasterSlaveDeterminationRelease masterSlaveDeterminationRelease ; |
| |
| MessageSend(H245_MSG_IDC, MSGTYP_MSD_RLS, (uint8*)&masterSlaveDeterminationRelease); |
| } |
| |
| void NewStatusDeterminationNumber() |
| { |
| StatusDeterminationNumber = RandGen.Rand() & 0xFFFFFF; // 0xFFFFFF max allowed |
| Print(" Status Det Number -> 0x%08x\n", StatusDeterminationNumber); |
| } |
| |
| void SetTimer() |
| { |
| RequestTimer(106, 0, TimerDuration, this); |
| } |
| void ResetTimer() |
| { |
| CancelTimer(106); |
| } |
| |
| MSDObserver *Observer; |
| uint8 TerminalType; |
| MSDState State; |
| MSDStatus Status; |
| uint32 StatusDeterminationNumber; |
| uint8 RetryCnt; |
| OsclRand RandGen; |
| }; |
| |
| #endif /* _SEMSD_ */ |