/*---------------------------------------------------------------------------* Project: Horizon File: cec_Control.h Copyright (C)2009 Nintendo Co., Ltd. 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. $Rev: 31256 $ *---------------------------------------------------------------------------*/ #ifndef NN_CEC_CTR_CEC_CONTROL_H_ #define NN_CEC_CTR_CEC_CONTROL_H_ #include #include namespace nn { namespace cec { namespace CTR { struct CecAllocFunc { void* (*allocFunc)(size_t); //!< メモリアロケート関数へのポインタです。 void (*freeFunc)(void*); //!< メモリ解放関数へのポインタです。 }; //------------------------------------------------------------ // 通知用 /*! @struct CecNotificationParam @brief 受信情報のBOX個々の情報 */ struct CecNotificationParam { nn::fnd::DateTimeParameters recvDate; //!< 受信日時 u32 cecTitleId; //!< BOXの cecTitleId u8 messageId[CEC_SIZEOF_MESSAGEID]; //!< 受信MessageのMessageID(先頭のMessageのみ) }; /*! @struct CecNotificationData @brief 受信情報 */ struct CecNotificationData { size_t num; //!< 項目数 s32 count; //!< 受信回数(本体起動から) 通信が行われるとこの値が増加します。 CecNotificationParam param[MESSAGE_BOX_NUM_MAX]; //!< 個々のBOXの情報 }; /*! @class CecControl @brief Cecの状態を変更・情報の取得を行います。 Cecデーモンの状態はシステムに管理され、自動的に動作しています。
MessageBoxへのアクセス(OpenMessageBox, ReadMessage, WriteMessage等)を行うと、 Cecデーモンの動作を中断してIDLE状態になります。
*/ class CecControl { public: enum ChangeDaemonState{ DAEMON_CHANGE_STATE_READY , DAEMON_CHANGE_STATE_STARTSCAN , DAEMON_CHANGE_STATE_STOP, DAEMON_CHANGE_STATE_STOP_DAEMON, DAEMON_CHANGE_STATE_START_DAEMON, DAEMON_CHANGE_STATE_RESET_FILTER, DAEMON_CHANGE_STATE_NDM_RESUME, DAEMON_CHANGE_STATE_NDM_SUSPEND }; /*! @brief @ref GetCecState で取得される、Cecの状態を示す値です。DAEMON_STATE_IDLE のときしか BOXにアクセスすることはできません。 */ enum DaemonState { DAEMON_STATE_STOP, //!< 動作していません DAEMON_STATE_IDLE, //!< 停止中 DAEMON_STATE_BUSY, //!< 処理中 DAEMON_STATE_SCAN, //!< スキャン中 DAEMON_STATE_READY, //!< READY状態(インターネット通信など、別の通信をしており、すれちがい通信に入っていない状態) DAEMON_STATE_COMMUNICATING //!< 通信中 }; CecControl(size_t bufSize); CecControl(); ~CecControl(); /*! :private * @brief cec に接続します。cec にアクセスするために最初に呼ぶ必要があります。 * @return nn::Result */ static nn::Result Initialize(); //static nn::Result Initialize(CecAllocFunc& cecAllocFunc); static nn::Result Initialize(nn::fnd::IAllocator& cecAllocFunc); #if 0 static nn::Result InitializeSys(); #endif /*! :private * @brief cec へのアクセスを終了します。 * @return nn::Result */ static nn::Result Finalize(); #if 0 static nn::Result FinalizeSys(); #endif static bool IsInitialized(); #if 0 static bool IsInitializedSys(); #endif /*! :private * @brief cec を Ready 状態に移行させます。nn::cec::Initialize() ~ Finalize() の間は呼ぶことはできません。 (暫定的に用意されたAPIです。今後のバージョンでは、cecの状態を直接変更するAPIは削除されます。) * @return nn::Result */ static nn::Result ReadyDaemon(); /*! * @brief cec の動作を開始させます。 MessageBox::CloseMessageBox の中で、 StartScanning(reset = false) が呼ばれます。 * @param[in] reset true をセットすると、BOXの内容を読み直して Scan を開始します。
また、記憶していた通信相手のリストも消去され、同じ相手と再接続することが可能になります。このとき、設定中のボックスだけでなく、全てのボックス(アプリ)のデータが、再度交換される可能性があります。
デバッグ時等、同じ相手と再接続する必要があるとき以外はtrueにしないでください。
リストの消去は、nn::cec::CTR::MessageBox::DeleteMessageBox() で BOXを削除したときも行われます。 * @return nn::Result * @retval ResultSuccess 成功しました。 * @retval ResultStateBusy Initialize が行われていないなどの理由で動作開始しませんでした。 * @retval 上記以外 失敗しました。 */ static nn::Result StartScanning(bool reset = false); /*! :private * @brief ndmからcecをSuspendさせます。 * @return nn::Result * @retval ResultSuccess 成功しました。 * @retval ResultStateBusy 停止処理を行いましたが、停止ステートになりませんでした。 * @retval 上記以外 失敗しました。 */ static nn::Result Suspend(); /*! * @brief cec の動作を手動で停止します。 通信途中だった場合、通信を中断して停止(IDLE)ステータスに移行します。
MessageBox にアクセスするには、停止状態である必要があります。
MessageBox::OpenMessageBox の中で、 StopScanning(b_Immediate = true) が呼ばれます。
事前にこの関数を使用することで、デーモンの動作を中断させず、停止状態になるのを待つことができます。

b_Asyncにtrueをセットしたとき、複数回呼んでキャンセルが発生したときなど、この関数から抜けたときに停止ステータスになっていない可能性があります。
この関数を呼んだ後に WriteMessage などを呼んでも、BUSY状態であるためにエラーになる可能性があるので注意してください。 * @param[in] b_Immediate true をセットすると、通信途中のデータの保存もキャンセルして停止させます。 * @param[in] b_Async true をセットすると、即座に返ります。 * @return nn::Result * @retval ResultSuccess 成功しました。 * @retval ResultStateBusy 停止処理を行いましたが、停止ステートになりませんでした。 * @retval 上記以外 失敗しました。 */ static nn::Result StopScanning(bool b_Immediate = false, bool b_Async = false); /*! :private * @brief CecDaemon を 停止させます。 (暫定的に用意されたAPIです。今後のバージョンでは、cecの状態を直接変更するAPIは削除されます。) 停止後は StartScanning を呼んでも動作開始しません。 * @return nn::Result */ static nn::Result StopDaemon(); /*! :private * @brief CecDaemon を 動作開始させます。 (暫定的に用意されたAPIです。今後のバージョンでは、cecの状態を直接変更するAPIは削除されます。) * @return nn::Result */ static nn::Result StartDaemon(); /*! :private * @brief 受信したMessageの情報を取得します。 * @param[in] cecTitleId すれちがい通信ID を指定します。 * @param[out] pCecInfoBuffer CecNotificationData を受け取るバッファを指定します。 * @param[in] size バッファのサイズを指定します。 * @return nn::Result */ static nn::Result GetCecInfoBuffer( u32 cecTitleId, u8 pCecInfoBuffer[], size_t size ); static nn::Result GetCecInfoBuffer( u8 pCecInfoBuffer[], size_t size ) { return GetCecInfoBuffer( 0, pCecInfoBuffer, size ); }; /*! * @brief CECの状態を取得します。 * @param[out] state 状態を示す @ref DaemonState が格納されます。 DAEMON_STATE_IDLE のときのみ、BOXにアクセス可能です。IDLE 以外の状態の遷移は外部から変更できない為、それぞれの状態をハンドリングする必要はありません。 * @return nn::Result * @retval ResultSuccess 成功しました。 */ static nn::Result GetCecState( DaemonState* state ); static nn::Result GetCecState( u32* state ); static bool IsDaemonBusy(void); /*! :private * @brief 受信の通知を受ける Event をセットします。 * @param[out] event 受信があったときに Signal される Event です。 * @return nn::Result */ static nn::Result GetCecRecvEventHandle( nn::os::Event* event ); static nn::Result GetChangeStateEventHandle( nn::os::Event& event ); static nn::cec::CTR::TitleId MakeCecTitleId(bit32 id, bit8 variation = 0x0); /* @brief NAND上の CECのBOX保存領域をフォーマットします。デバッグ用です。 */ static nn::Result FormatSaveData(); private: static bool s_Initialized; static bool s_NdmSuspended; }; //! @name Initialize / Finalize //@{ /*! * @brief CEC Daemon に接続します。CEC MessageBox にアクセスするために最初に呼ぶ必要があります。 * @param[in] cecAllocFunc CEC ライブラリが使用するアロケータを指定します。 CEC ライブラリのMessageデータ処理に必要なメモリを確保するために 使用されます。最大で扱うMessageデータサイズ × 2 程度のメモリが使用されます。 * @return nn::Result */ nn::Result Initialize(nn::fnd::IAllocator& cecAllocFunc); /*! * @brief CEC Daemon に接続します。CEC MessageBox にアクセスするために最初に呼ぶ必要があります。 * @return nn::Result * @retval ResultSuccess 成功しました。 * @retval 上記以外 失敗しました。 */ nn::Result Initialize(); inline nn::Result Initialize() { return CecControl::Initialize(); } nn::Result Initialize(nn::cec::CTR::CecAllocFunc& cecAllocFunc); inline nn::Result Initialize(nn::fnd::IAllocator& cecAllocFunc) { return CecControl::Initialize(cecAllocFunc); } /*! * @brief CEC Daemon へのアクセスを終了します。 * @return nn::Result * @retval ResultSuccess 成功しました。 * @retval 上記以外 失敗しました。 */ nn::Result Finalize(); inline nn::Result Finalize() { return CecControl::Finalize(); } //@} //! @name 受信通知 //@{ /*! * @brief 受信の通知を受ける Event を指定します。 すれちがい通信が発生したときにSignalされるEventです。
通信したことをリアルタイムに知りたいときに使用することができます。
フォアグラウンドのアプリケーション宛のデータがあるかどうかは、 @ref GetCecInfoBuffer 等で確認することができます。 * @param[out] event 受信があったときに Signal される Event です。 * @return nn::Result * @retval ResultSuccess 成功しました。 */ nn::Result GetCecRecvEventHandle( nn::os::Event* event ); inline nn::Result GetCecRecvEventHandle( nn::os::Event* event ) { return CecControl::GetCecRecvEventHandle( event ); } /*! * @brief 直前の通信で受信したMessageの情報を取得します。 @ref GetCecRecvEventHandle を使用して受信の通知を受け取った後、 フォアグラウンドのアプリケーション宛のデータがあるかどうかを調べる時等に使用できます。
グルーピングされた複数のMessageを受け取ったときでも、取得できる情報は1つ分だけです。
また、重複していたために破棄された受信データの情報は入りません。 * @param[in] cecTitleId すれちがい通信ID を指定します。 * @param[out] pCecInfoBuffer CecNotificationData を受け取るバッファを指定します。 * @param[in] size バッファのサイズを指定します。 * @return nn::Result * @retval ResultSuccess 成功しました。 * @retval ResultNoData 取得できるデータがありませんでした。 */ nn::Result GetCecInfoBuffer( u32 cecTitleId, u8 pCecInfoBuffer[], size_t size ); nn::Result GetCecInfoBuffer( u8 pCecInfoBuffer[], size_t size ); inline nn::Result GetCecInfoBuffer( u32 cecTitleId, u8 pCecInfoBuffer[], size_t size ) { return CecControl::GetCecInfoBuffer(cecTitleId, pCecInfoBuffer, size ); } inline nn::Result GetCecInfoBuffer( u8 pCecInfoBuffer[], size_t size ) { return CecControl::GetCecInfoBuffer(0, pCecInfoBuffer, size ); } //@} /*! @brief 20bit のユニーク ID から、すれちがい通信で使用する 32bit の すれちがい通信ID(CecTitleId) を生成します。 @param[in] id 20bit の ユニークID です。複数タイトル間で共通のボックスを使用して通信したい場合は、どちらか片方のユニーク ID を指定してください。 @param[in] variation 使用しません。 * @return CecTitleId */ nn::cec::CTR::TitleId MakeCecTitleId(bit32 id, bit8 variation = 0x0); inline nn::cec::CTR::TitleId MakeCecTitleId(bit32 id, bit8 variation) { return CecControl::MakeCecTitleId(id, variation); } } // end of namespace CTR } // end of namespace cec } // end of namespace nn #endif // ifndef NN_CEC_CTR_CEC_CONTROL_H_