/*---------------------------------------------------------------------------*
  Project:  NitroSDK - WM - libraries
  File:     wm_standard.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_standard.c,v $
  Revision 1.10  2004/10/29 02:53:25  terui
  Temporarily changed WM_StartScanEx to a private function.

  Revision 1.9  2004/10/27 04:23:57  ooe
  Deleted unnecessary OS_Printf.

  Revision 1.8  2004/10/26 08:21:44  ooe
  Added WM_StartScanEx.

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

  Revision 1.6  2004/10/05 09:45:28  terui
  Standardized the MAC address as the u8 type array

  Revision 1.5  2004/10/01 11:05:22  terui
  Made a subtle change to the warning message

  Revision 1.4  2004/09/15 08:31:43  terui
  Corrected mistakes in method used to determine align check during debug builds.

  Revision 1.3  2004/09/15 02:19:48  terui
  Replaced the warning about MP send/receive size with the warning required
  when sending/receiving MP packets

  Revision 1.2  2004/09/10 12:05:40  seiki_masashi
  Changed it so the number of bytes sent for key sharing is concealed in the library

  Revision 1.1  2004/09/10 11:03:30  terui
  Divided wm.c, so made new upload.


  $NoKeywords: $
 *---------------------------------------------------------------------------*/

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


/*---------------------------------------------------------------------------*
    Internal function definitions
 *---------------------------------------------------------------------------*/
static BOOL     WmCheckParentParameter( const WMParentParam* param );


/*---------------------------------------------------------------------------*
  Name:         WM_Enable

  Description:  Enables wireless hardware.
                The internal state transitions from READY to STOP.

  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_Enable( WMCallbackFunc callback )
{
    WMErrCode   result;

    // Cannot execute if not READY state
    result = WMi_CheckState( WM_STATE_READY );
    WM_CHECK_RESULT( result );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_ENABLE , callback );

    // FIFO notification to ARM7
    {
        WMArm9Buf*  p   = WMi_GetSystemWork();
    
        result = WMi_SendCommand(
            WM_APIID_ENABLE , 3 ,
            (u32)( p->WM7 ) ,
            (u32)( p->status ) ,
            (u32)( p->fifo7to9 )
        );
        WM_CHECK_RESULT( result );
    }

    // Normal end
    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_Disable

  Description:  Disables wireless hardware.
                Internal state transitions from STOP to READY.

  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_Disable( WMCallbackFunc callback )
{
    WMErrCode   result;

    // Cannot execute if not STOP state
    result = WMi_CheckState( WM_STATE_STOP );
    WM_CHECK_RESULT( result );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_DISABLE , callback );

    // FIFO notification to ARM7
    result = WMi_SendCommand( WM_APIID_DISABLE , 0 );
    WM_CHECK_RESULT( result );

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_PowerOn

  Description:  Starts the wireless hardware.
                The internal state transitions from STOP to IDLE.

  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_PowerOn( WMCallbackFunc callback )
{
    WMErrCode   result;

    // Cannot execute if not STOP state
    result = WMi_CheckState( WM_STATE_STOP );
    WM_CHECK_RESULT( result );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_POWER_ON , callback );

    // FIFO notification to ARM7
    result = WMi_SendCommand( WM_APIID_POWER_ON , 0 );
    WM_CHECK_RESULT( result );

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_PowerOff

  Description:  Shuts down the wireless hardware.
                Internal state transitions from IDLE to STOP.

  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_PowerOff( WMCallbackFunc callback )
{
    WMErrCode   result;

    // Cannot execute if not IDLE state
    result = WMi_CheckState( WM_STATE_IDLE );
    WM_CHECK_RESULT( result );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_POWER_OFF , callback );

    // FIFO notification to ARM7
    result = WMi_SendCommand( WM_APIID_POWER_OFF , 0 );
    WM_CHECK_RESULT( result );

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_Initialize

  Description:  Initializes WM.

  Arguments:    wmSysBuf    -   Pointer to buffer secured by call source.
                                The buffer size must be only WM_SYSTEM_BUF_SIZE.
                callback    -   The callback function called when asynchronous process ends.
                dmaNo       -   DMA number used by WM.

  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_Initialize( void* wmSysBuf , WMCallbackFunc callback , u16 dmaNo )
{
    WMErrCode   result;

    // Execute the initialization
    result = WM_Init( wmSysBuf , dmaNo );
    WM_CHECK_RESULT( result );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_INITIALIZE , callback );

    // FIFO notification to ARM7
    {
        WMArm9Buf*  p = WMi_GetSystemWork();
    
        result = WMi_SendCommand(
            WM_APIID_INITIALIZE , 3 ,
            (u32)( p->WM7 ) , 
            (u32)( p->status ) ,
            (u32)( p->fifo7to9 )
        );
        WM_CHECK_RESULT( result );
    }

    // Normal end
    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_Reset

  Description:  Resets wireless library and retruns to state immediately after initialization.

  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_Reset( WMCallbackFunc callback )
{
    WMErrCode   result;

    // Confirm that wireless hardware has started
    result = WMi_CheckIdle();
    WM_CHECK_RESULT( result );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_RESET , callback );
    
    // FIFO notification to ARM7
    result = WMi_SendCommand( WM_APIID_RESET , 0 );
    WM_CHECK_RESULT( result );

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_End

  Description:  Ends wirelss library.

  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_End( WMCallbackFunc callback )
{
    WMErrCode   result;

    // Cannot execute if not IDLE state
    result = WMi_CheckState( WM_STATE_IDLE );
    WM_CHECK_RESULT( result );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_END , callback );

    // FIFO notification to ARM7
    result = WMi_SendCommand( WM_APIID_END , 0 );
    WM_CHECK_RESULT( result );

    // Perform the process for ending the WM library on the ARM9 side inside the callback

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_SetParentParameter

  Description:  Sets parent parameters.

  Arguments:    callback    -   The callback function called when asynchronous process ends.
                pparaBuf    -   Pointer to structure showing parent parameters.
                                Note that pparaBuf and pparaBuf->userGameInfo are forcibly cache stored.

  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_SetParentParameter( WMCallbackFunc callback , const WMParentParam* pparaBuf )
{
    WMErrCode   result;

    // Cannot execute if not IDLE state
    result = WMi_CheckState( WM_STATE_IDLE );
    WM_CHECK_RESULT( result );

    // Check the parameter
    if( pparaBuf == NULL )
    {
        WM_WARNING( "Parameter \"pparaBuf\" must not be NULL.\n" );
        return WM_ERRCODE_INVALID_PARAM;
    }
    if( (u32)pparaBuf & 0x01f )
    {
        // For alignment check, warning only, not error
        WM_WARNING( "Parameter \"pparaBuf\" is not 32-byte aligned.\n" );
    }
    if( pparaBuf->userGameInfoLength > 0 )
    {
        if( pparaBuf->userGameInfo == NULL )
        {
            WM_WARNING( "Parameter \"pparaBuf->userGameInfo\" must not be NULL.\n" );
            return WM_ERRCODE_INVALID_PARAM;
        }
        if( (u32)( pparaBuf->userGameInfo ) & 0x01f )
        {
            // For alignment check, warning only, not error
            WM_WARNING( "Parameter \"pparaBuf->userGameInfo\" is not 32-byte aligned.\n" );
        }
    }

    // Check maximum data transfer length
    if(
        ( pparaBuf->parentMaxSize + (pparaBuf->KS_Flag ? WM_SIZE_KS_PARENT_DATA + WM_SIZE_MP_PARENT_PADDING : 0) > WM_SIZE_MP_DATA_MAX ) ||
        ( pparaBuf->childMaxSize + (pparaBuf->KS_Flag ? WM_SIZE_KS_CHILD_DATA + WM_SIZE_MP_CHILD_PADDING : 0) > WM_SIZE_MP_DATA_MAX )
    )
    {
        WM_WARNING( "Transfer data size is over %d byte.\n" , WM_SIZE_MP_DATA_MAX );
        return WM_ERRCODE_INVALID_PARAM;
    }
    (void)WmCheckParentParameter( pparaBuf );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_SET_P_PARAM , callback );

    // Write specified buffer's cache
    DC_StoreRange( (void*)pparaBuf , WM_PARENT_PARAM_SIZE );
    if( pparaBuf->userGameInfoLength > 0 )
    {
        DC_StoreRange( pparaBuf->userGameInfo , pparaBuf->userGameInfoLength );
    }

    // FIFO notification to ARM7
    result = WMi_SendCommand( WM_APIID_SET_P_PARAM , 1 , (u32)pparaBuf );
    WM_CHECK_RESULT( result );

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WmCheckParentParameter

  Description:  This is a debug function, used to check whether the set parent
                parameter falls within the admissible range shown in the
                guidelines.

  Arguments:    param   -   Pointer to set parent parameter being checked.

  Returns:      BOOL    -   Returns TRUE if no problem, or FALSE if setting 
                            value not admissible.
 *---------------------------------------------------------------------------*/
static BOOL
WmCheckParentParameter( const WMParentParam* param )
{
    // User game information can be up to 112 bytes
    if( param->userGameInfoLength > WM_SIZE_USER_GAMEINFO )
    {
        OS_TWarning( "User gameInfo length must be less than %d .\n" , WM_SIZE_USER_GAMEINFO );
        return FALSE;
    }
    // Beacon transmission interval is 10 to 1000
    if( ( param->beaconPeriod < 10 ) || ( param->beaconPeriod > 1000 ) )
    {
        OS_TWarning( "Beacon send period must be between 10 and 1000 .\n" );
        return FALSE;
    }
    // Connection channels are 1 to 14
    if( ( param->channel < 1 ) || ( param->channel > 14 ) )
    {
        OS_TWarning( "Channel must be between 1 and 14 .\n" );
        return FALSE;
    }
#if 0
    // Total size of data sent/received can be up to 368 bytes
    if( 368 < ( param->parentMaxSize + ( param->childMaxSize * param->maxEntry ) ) )
    {
        OS_TWarning( "Transfer data size is over 368 byte.\n" );
        return FALSE;
    }
#else
    // Each MP communication can last a duration of up to 5600us
    {
        s32     mp_time;
    
        // The time it takes for one MP communication is calculated in units of us
        mp_time = (
            (       // --- The parent transmission part ---
                96          // Preamble
                + (
                    24          // 802.11 Header
                    + 4         // TXOP + PollBitmap
                    + 2         // wmHeader
                    + param->parentMaxSize
                    + 4         // wmFooter( parent )
                    + 4         // FCS
                ) * 4       // 4us per 1 byte
            )
            + (     // --- The child transmission part ---
                (
                    10          // SIFS
                    + 96        // Preamble
                    + (
                        24          // 802.11 Header
                        + 2         // wmHeader
                        + param->childMaxSize
                        + 2         // wmFooter( child )
                        + 4         // FCS
                    ) * 4       // 4us per 1 byte
                    + 6         // time to spare
                ) * param->maxEntry
            ) +
            (       // --- The MP ACK transmission part ---
                10          // SIFS
                + 96        // Preamble
                + (
                    24          // 802.11 Header
                    + 4         // ACK
                    + 4         // FCS
                ) * 4       // 4us per 1 byte
            )
        );
    
        if( mp_time > 5600 )
        {
            OS_TWarning( "It is required %dus to transfer each MP packet.\nThat should not exceed 5600us.\n" , mp_time );
            return FALSE;
        }
    }
#endif

    return TRUE;
}

/*---------------------------------------------------------------------------*
  Name:         WM_StartParent

  Description:  Starts communication as parent.

  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_StartParent( WMCallbackFunc callback )
{
    WMErrCode   result;

    // Cannot execute if not IDLE state
    result = WMi_CheckState( WM_STATE_IDLE );
    WM_CHECK_RESULT( result );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_START_PARENT , callback );

    // FIFO notification to ARM7
    result = WMi_SendCommand( WM_APIID_START_PARENT , 0 );
    WM_CHECK_RESULT( result );

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_EndParent

  Description:  Ends communication as parent.

  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_EndParent( WMCallbackFunc callback )
{
    WMErrCode   result;

    // Cannot execute if not PARENT state
    result = WMi_CheckState( WM_STATE_PARENT );
    WM_CHECK_RESULT( result );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_END_PARENT , callback );

    // FIFO notification to ARM7
    result = WMi_SendCommand( WM_APIID_END_PARENT , 0 );
    WM_CHECK_RESULT( result );

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_StartScan

  Description:  Starts parent scan as child.
                Gets one parent information with one call.
                It is OK to consecutively call without calling WM_EndScan.

  Arguments:    callback    -   The callback function called when asynchronous process ends.
                param       -   Pointer to structure showing scan information.
                                For scan result information, the ARM7 writes directly to param->scanBuf,
                                so it must match cache line.
                                Also, note that param structure is forcibly cache stored.
                                

  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_StartScan( WMCallbackFunc callback , const WMScanParam* param )
{
    WMErrCode   result;

    // Cannot execute if not IDLE CALSS1 SCAN state
    result = WMi_CheckStateEx( 3 , WM_STATE_IDLE , WM_STATE_CLASS1 , WM_STATE_SCAN );
    WM_CHECK_RESULT( result );

    // Check the parameter
    if( param == NULL )
    {
        WM_WARNING( "Parameter \"param\" must not be NULL.\n" );
        return WM_ERRCODE_INVALID_PARAM;
    }
    if( param->scanBuf == NULL )
    {
        WM_WARNING( "Parameter \"param->scanBuf\" must not be NULL.\n" );
        return WM_ERRCODE_INVALID_PARAM;
    }
    if( ( param->channel < 1 ) || ( param->channel > 14 ) )
    {
        WM_WARNING( "Parameter \"param->channel\" must be between 1 and 14.\n" );
        return WM_ERRCODE_INVALID_PARAM;
    }
    if( (u32)param & 0x01f )
    {
        // For alignment check, warning only, not error
        WM_WARNING( "Parameter \"param\" is not 32-byte aligned.\n" );
    }
    if( (u32)( param->scanBuf ) & 0x01f )
    {
        // For alignment check, warning only, not error
        WM_WARNING( "Parameter \"param->scanBuf\" is not 32-byte aligned.\n" );
    }

    // Write specified buffer's cache
    DC_StoreRange( (void*)param , sizeof( WMScanParam ) );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_START_SCAN , callback );

    // FIFO notification to ARM7
    {
        WMStartScanReq* Req =
            (WMStartScanReq*)( WMi_GetSystemWork()->fifo9to7 );
    
        Req->apiid          = WM_APIID_START_SCAN;
        Req->channel        = param->channel;
        Req->scanBuf        = param->scanBuf;
        Req->maxChannelTime = param->maxChannelTime;
        Req->bssid[0]       = param->bssid[0];
        Req->bssid[1]       = param->bssid[1];
        Req->bssid[2]       = param->bssid[2];
        Req->bssid[3]       = param->bssid[3];
        Req->bssid[4]       = param->bssid[4];
        Req->bssid[5]       = param->bssid[5];
        result = WMi_SendCommand( WM_APIID_START_SCAN , 0 );
        WM_CHECK_RESULT( result );
    }

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_StartScanEx

  Description:  Starts parent scan as child.
                Gets multiple parent information with one call.
                It is OK to consecutively call without calling WM_EndScan.

  Arguments:    callback - The callback function called when asynchronous process ends.
                param    - Pointer to structure showing scan information.
                           For scan result information, ARM7 writes directly to param->scanBuf,
                           so it must match cache line.
                           Also, note that param structure is forcibly cache stored.

  Returns:      int      - Returns WM_ERRCODE_* type process results.
 *---------------------------------------------------------------------------*/
/*
 * As of 10/29/2004
 * We will temporarily make this function private since we haven't been able to sufficiently verify operation.
 */
WMErrCode
WMi_StartScanEx( WMCallbackFunc callback , const WMScanParam* param )
{
    WMErrCode result;

    // Not executable outside of IDLE CALSS1 SCAN state
    result = WMi_CheckStateEx( 3 , WM_STATE_IDLE , WM_STATE_CLASS1 , WM_STATE_SCAN );
    WM_CHECK_RESULT( result );

    // parameter check
    if( param == NULL )
    {
        WM_WARNING( "Parameter \"param\" must not be NULL.\n" );
        return WM_ERRCODE_INVALID_PARAM;
    }
    if( param->scanBuf == NULL )
    {
        WM_WARNING( "Parameter \"param->scanBuf\" must not be NULL.\n" );
        return WM_ERRCODE_INVALID_PARAM;
    }
    if( ( param->channel < 1 ) || ( param->channel > 14 ) )
    {
        WM_WARNING( "Parameter \"param->channel\" must be between 1 and 14.\n" );
        return WM_ERRCODE_INVALID_PARAM;
    }
    if( (u32)param & 0x01f )
    {
        // align check is a warning only, not an error
        WM_WARNING( "Parameter \"param\" is not 32-byte aligned.\n" );
    }
    if( (u32)( param->scanBuf ) & 0x01f )
    {
        // align check is a warning only, not an error
        WM_WARNING( "Parameter \"param->scanBuf\" is not 32-byte aligned.\n" );
    }

    // write specified buffer cache
    DC_StoreRange( (void*)param , sizeof( WMScanParam ) );

    // register callback function
    WMi_SetCallbackTable( WM_APIID_START_SCAN , callback );

    // notify ARM7 with FIFO
    {
        WMStartScanReq* Req =
            (WMStartScanReq*)( WMi_GetSystemWork()->fifo9to7 );

        Req->apiid          = WM_APIID_START_SCAN_EX;
        Req->channel        = param->channel;
        Req->scanBuf        = param->scanBuf;
        Req->maxChannelTime = param->maxChannelTime;
        Req->bssid[0]       = param->bssid[0];
        Req->bssid[1]       = param->bssid[1];
        Req->bssid[2]       = param->bssid[2];
        Req->bssid[3]       = param->bssid[3];
        Req->bssid[4]       = param->bssid[4];
        Req->bssid[5]       = param->bssid[5];
        result = WMi_SendCommand( WM_APIID_START_SCAN_EX , 0 );
        WM_CHECK_RESULT( result );
    }

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_EndScan

  Description:  Ends scan process as child.

  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_EndScan( WMCallbackFunc callback )
{
    WMErrCode   result;

    // Cannot execute if not SCAN state
    result = WMi_CheckState( WM_STATE_SCAN );
    WM_CHECK_RESULT( result );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_END_SCAN , callback );

    // FIFO notification to ARM7
    result = WMi_SendCommand( WM_APIID_END_SCAN , 0 );
    WM_CHECK_RESULT( result );

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_StartConnect

  Description:  Start connection to parent as child.

  Arguments:    callback    -   The callback function called when asynchronous process ends.
                pInfo       -   Information of connected parent.
                                Specifies structure obtained with WM_StartScan.
                                Note that this structure is forcibly
                                cache stored.
                ssid        -   child information notified to parent (24Byte(WM_SIZE_CHILD_SSID) fixed size)

  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_StartConnect( WMCallbackFunc callback , const WMBssDesc* pInfo, const u8 *ssid )
{
    WMErrCode   result;

    // Cannot execute if not IDLE state
    result = WMi_CheckState( WM_STATE_IDLE );
    WM_CHECK_RESULT( result );

    // Check the parameter
    if( pInfo == NULL )
    {
        WM_WARNING( "Parameter \"pInfo\" must not be NULL.\n" );
        return WM_ERRCODE_INVALID_PARAM;
    }
    if( (u32)pInfo & 0x01f )
    {
        // For alignment check, warning only, not error
        WM_WARNING( "Parameter \"pInfo\" is not 32-byte aligned.\n" );
    }

    // Write specified buffer's cache
    DC_StoreRange( (void*)pInfo, WM_BSS_DESC_SIZE );

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_START_CONNECT , callback );

    // FIFO notification to ARM7
    {
        WMStartConnectReq*  Req =
            (WMStartConnectReq*)( WMi_GetSystemWork()->fifo9to7 );
    
        Req->apiid  = WM_APIID_START_CONNECT;
        Req->pInfo  = (WMBssDesc*)pInfo;
        if( ssid != NULL )
        {
            MI_CpuCopy8( ssid , Req->ssid , WM_SIZE_CHILD_SSID );
        }
        else
        {
            MI_CpuClear8( Req->ssid, WM_SIZE_CHILD_SSID );
        }
        result = WMi_SendCommand( WM_APIID_START_CONNECT , 0 );
        WM_CHECK_RESULT( result );
    }

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_Disconnect

  Description:  Cuts established connection.

  Arguments:    callback    -   The callback function called when asynchronous process ends.
                aid         -   AID of communication partner to disconnect.
                                When parent, separately disconnects children with IDs 1-15.
                                When child, ends communication with parent havind ID 0.

  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_Disconnect( WMCallbackFunc callback , u16 aid )
{
    WMErrCode   result;
    WMArm9Buf*  p = WMi_GetSystemWork();

    // Check the state
    result = WMi_CheckStateEx( 5 ,
        WM_STATE_PARENT , WM_STATE_MP_PARENT ,
        WM_STATE_CHILD , WM_STATE_MP_CHILD , WM_STATE_DCF_CHILD
    );
    WM_CHECK_RESULT( result );

    if(     // Cache for p->status->state is destroyed
        ( p->status->state == WM_STATE_PARENT ) ||
        ( p->status->state == WM_STATE_MP_PARENT )
    )
    {
        // For parent
        if( ( aid < 1 ) || ( aid > WM_NUM_MAX_CHILD ) )
        {
            WM_WARNING( "Parameter \"aid\" must be between 1 and %d.\n" , WM_NUM_MAX_CHILD );
            return WM_ERRCODE_INVALID_PARAM;
        }
        DC_InvalidateRange( &( p->status->child_bitmap ) , 2 );
        if( ! ( p->status->child_bitmap & ( 0x0001 << aid ) ) )
        {
            WM_WARNING( "There is no child that have aid %d.\n" , aid );
            return WM_ERRCODE_NO_CHILD;
        }
    }
    else
    {
        // For child
        if( aid != 0 )
        {
            WM_WARNING( "Now child mode , so aid must be 0.\n" );
            return WM_ERRCODE_INVALID_PARAM;
        }
    }

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_DISCONNECT , callback );

    // FIFO notification to ARM7
    result = WMi_SendCommand( WM_APIID_DISCONNECT , 1 , (u32)( 0x0001 << aid ) );
    WM_CHECK_RESULT( result );

    return WM_ERRCODE_OPERATING;
}

/*---------------------------------------------------------------------------*
  Name:         WM_DisconnectChildren

  Description:  Disconnects each child with connection established. A parent function.

  Arguments:    callback    -   The callback function called when asynchronous process ends.
                aidBitmap   -   AID bit field of child to disconnect.
                                Lowest bit is ignored, and bits 1-15 show each of the children of AID 1-15.
                                The bit showing unconnected child is ingnored, so
                                so specify 0xFFFF when disconnecting all children regardless of connection state.

  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_DisconnectChildren( WMCallbackFunc callback , u16 aidBitmap )
{
    WMErrCode   result;
    WMArm9Buf*  p = WMi_GetSystemWork();

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

    // Check the parameter
    DC_InvalidateRange( &( p->status->child_bitmap ) , 2 );
    if( ! ( p->status->child_bitmap & aidBitmap & 0xfffe ) )
    {
        WM_WARNING( "There is no child that is included in \"aidBitmap\" %04x_.\n" , aidBitmap );
        return WM_ERRCODE_NO_CHILD;
    }

    // Register the callback function
    WMi_SetCallbackTable( WM_APIID_DISCONNECT , callback );

    // FIFO notification to ARM7
    result = WMi_SendCommand( WM_APIID_DISCONNECT , 1 , (u32)aidBitmap );
    WM_CHECK_RESULT( result );

    return WM_ERRCODE_OPERATING;
}

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

