/*---------------------------------------------------------------------------*
  Project:  NitroSDK - WM - libraries
  File:     wm_ks.c

  Copyright 2003,2004 Nintendo.  All rights reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law.  They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Log: wm_ks.c,v $
  Revision 1.3  2004/11/02 07:26:51  terui
  Fixed comments.

  Revision 1.2  2004/10/22 04:37:28  terui
  Changed functions that return int type as WMErrCode so that they return WMErrCode enumerator type.

  Revision 1.1  2004/09/10 11:03:30  terui
  New upload reflecting breakup of wm.c. 
  
  $NoKeywords: $
 *---------------------------------------------------------------------------*/

#include    <nitro/wm.h>
#include    "wm_arm9_private.h"


/*---------------------------------------------------------------------------*
  Name:         WM_StartKeySharing

  Description:  Enables key sharing function.
                By performing MP communication after enabling the feature, key sharing
                communication occurs accompanying MP communication.

  Arguments:    callback    -   The callback function called when asynchronous process ends.
                buf         -   pointer to buffer storing key information
                                ARM7 writes data directly so be careful of cache.

  Returns:      WMErrCode   -   Returns process results. WM_ERRCODE_OPERATING is returned
  					when an asynchronous process started normally. After that, asynchronous
                                	process results are again passed to callback.
 *---------------------------------------------------------------------------*/
WMErrCode
WM_StartKeySharing( WMCallbackFunc callback , WMKeySetBuf* buf )
{
#pragma unused(buf)
    WMErrCode   result;
    WMArm9Buf*  p   = WMi_GetSystemWork();

    // state check
    result = WMi_CheckStateEx( 2 , WM_STATE_MP_PARENT , WM_STATE_MP_CHILD );
    WM_CHECK_RESULT( result );

    // confirm MP status
    DC_InvalidateRange( &( p->status->mp_flag ) , 4 );
    if( p->status->mp_flag == FALSE )
    {
        WM_WARNING( "It is not MP mode now.\n" );
        return WM_ERRCODE_ILLEGAL_STATE;
    }

    {
        p->ksFlag = TRUE;
        result = WM_StartDataSharing( &( p->keySharingInfo ), WM_PORT_KS , 0xffff , WM_KEYDATA_SIZE , TRUE );
        {
            WMCallback cb;
            cb.apiid = WM_APIID_START_KS;
            cb.errcode = (u16)result;
            callback( &cb );
        }
    }

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_EndKeySharing

  Description:  Disable key sharing function.

  Arguments:    callback    -   The callback function called when asynchronous process ends.

  Returns:      WMErrCode   -   Returns process results. WM_ERRCODE_OPERATING is returned
  					when an asynchronous process started normally. After that, asynchronous
                                	process results are again passed to callback.
 *---------------------------------------------------------------------------*/
WMErrCode
WM_EndKeySharing( WMCallbackFunc callback )
{
    WMErrCode   result;
    WMArm9Buf*  p   = WMi_GetSystemWork();

    // Check state
    result = WMi_CheckStateEx( 2 , WM_STATE_MP_PARENT , WM_STATE_MP_CHILD );
    WM_CHECK_RESULT( result );

    // Confirm KS status
    DC_InvalidateRange( &( p->status->ks_flag ) , 4 );
    if( p->status->ks_flag == FALSE )
    {
        WM_WARNING( "It is not key-sharing mode now.\n" );
        return WM_ERRCODE_ILLEGAL_STATE;
    }

    {
        result = WM_EndDataSharing( &( p->keySharingInfo ) );
        p->ksFlag = FALSE;
        {
            WMCallback cb;
            cb.apiid = WM_APIID_END_KS;
            cb.errcode = (u16)result;
            callback( &cb );
        }
    }

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_GetKeySet

  Description:  Reads one key-shared key set data.

  Arguments:    keySet      -   Pointer to buffer that reads key set.
                                The buffer provided by WM_StartKeySharing specifies a separate buffer.

  Returns:      MWErrCode   -   Returns process results.
 *---------------------------------------------------------------------------*/
WMErrCode
WM_GetKeySet( WMKeySet* keySet )
{
    WMErrCode   result;
    u16         sendData[WM_KEYDATA_SIZE/sizeof(u16)];
    WMDataSet   ds;
    WMArm9Buf*  p   = WMi_GetSystemWork();

    // Check state
    result = WMi_CheckStateEx( 2 , WM_STATE_MP_PARENT , WM_STATE_MP_CHILD );
    WM_CHECK_RESULT( result );

    // Check state
    if ( p->ksFlag == FALSE )
    {
        WM_WARNING( "It is not key-sharing mode.\n" );
        return WM_ERRCODE_ILLEGAL_STATE;
    }

    {
        sendData[0] = (u16)PAD_Read();
        result = WM_StepDataSharing( &( p->keySharingInfo ), sendData, &ds );
        if ( result == WM_ERRCODE_SUCCESS )
        {
            keySet->seqNum = p->keySharingInfo.currentSeqNum;
            
            {
                u16 iAid;
                for ( iAid = 0; iAid < 16; iAid ++ )
                {
                    u16* keyData;
                    keyData = WM_GetSharedDataAddress( &( p->keySharingInfo ), &ds, iAid );
                    if ( keyData != NULL )
                    {
                        keySet->key[iAid] = keyData[0];
                    }
                    else
                    {
                        // Destination that failed to receive is 0
                        keySet->key[iAid] = 0;
                    }
                }
            }
            return WM_ERRCODE_SUCCESS;  // Succesfully completed
        }
        else
        {
            return result;
        }
    }
}

/*---------------------------------------------------------------------------*
    End of file
 *---------------------------------------------------------------------------*/
