1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     cec_Control.h
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 31256 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_CEC_CTR_CEC_CONTROL_H_
17 #define NN_CEC_CTR_CEC_CONTROL_H_
18 #include <nn/fnd.h>
19 #include <nn/cec/CTR/cec_Api.h>
20 
21 namespace nn {
22 namespace cec {
23 namespace CTR {
24 
25 struct CecAllocFunc
26 {
27     void* (*allocFunc)(size_t);  //!< メモリアロケート関数へのポインタです。
28     void  (*freeFunc)(void*);    //!< メモリ解放関数へのポインタです。
29 };
30 
31 //------------------------------------------------------------
32 // 通知用
33 
34 /*!
35     @struct     CecNotificationParam
36     @brief      受信情報のBOX個々の情報
37 */
38 struct CecNotificationParam
39 {
40     nn::fnd::DateTimeParameters     recvDate;       //!<    受信日時
41     u32                             cecTitleId;     //!<    BOXの cecTitleId
42     u8                              messageId[CEC_SIZEOF_MESSAGEID];    //!< 受信MessageのMessageID(先頭のMessageのみ)
43 };
44 
45 /*!
46     @struct     CecNotificationData
47     @brief      受信情報
48 */
49 struct CecNotificationData
50 {
51     size_t  num;                //!< 項目数
52     s32     count;              //!< 受信回数(本体起動から) 通信が行われるとこの値が増加します。
53     CecNotificationParam param[MESSAGE_BOX_NUM_MAX];    //!< 個々のBOXの情報
54 };
55 
56 
57 /*!
58     @class CecControl
59     @brief Cecの状態を変更・情報の取得を行います。
60 
61            Cecデーモンの状態はシステムに管理され、自動的に動作しています。<br>
62            MessageBoxへのアクセス(OpenMessageBox, ReadMessage, WriteMessage等)を行うと、
63            Cecデーモンの動作を中断してIDLE状態になります。<br>
64 
65 */
66 
67 class CecControl {
68 
69 public:
70 
71     enum ChangeDaemonState{
72         DAEMON_CHANGE_STATE_READY ,
73         DAEMON_CHANGE_STATE_STARTSCAN ,
74         DAEMON_CHANGE_STATE_STOP,
75         DAEMON_CHANGE_STATE_STOP_DAEMON,
76         DAEMON_CHANGE_STATE_START_DAEMON,
77         DAEMON_CHANGE_STATE_RESET_FILTER,
78 
79         DAEMON_CHANGE_STATE_NDM_RESUME,
80         DAEMON_CHANGE_STATE_NDM_SUSPEND
81 
82     };
83 
84     /*!
85         @brief @ref GetCecState で取得される、Cecの状態を示す値です。DAEMON_STATE_IDLE のときしか BOXにアクセスすることはできません。
86     */
87     enum DaemonState
88     {
89         DAEMON_STATE_STOP,          //!< 動作していません
90         DAEMON_STATE_IDLE,          //!< 停止中
91         DAEMON_STATE_BUSY,          //!< 処理中
92         DAEMON_STATE_SCAN,          //!< スキャン中
93         DAEMON_STATE_READY,         //!< READY状態(インターネット通信など、別の通信をしており、すれちがい通信に入っていない状態)
94         DAEMON_STATE_COMMUNICATING  //!< 通信中
95     };
96 
97 
98     CecControl(size_t bufSize);
99     CecControl();
100     ~CecControl();
101 
102     /*!
103     :private
104      * @brief       cec に接続します。cec にアクセスするために最初に呼ぶ必要があります。
105      * @return      nn::Result
106      */
107     static nn::Result  Initialize();
108     //static nn::Result  Initialize(CecAllocFunc& cecAllocFunc);
109     static nn::Result  Initialize(nn::fnd::IAllocator& cecAllocFunc);
110     #if 0
111     static nn::Result  InitializeSys();
112     #endif
113 
114     /*!
115     :private
116      * @brief       cec へのアクセスを終了します。
117      * @return      nn::Result
118      */
119     static nn::Result  Finalize();
120 
121     #if 0
122     static nn::Result  FinalizeSys();
123     #endif
124 
125 
126     static bool IsInitialized();
127     #if 0
128     static bool IsInitializedSys();
129     #endif
130 
131     /*!
132      :private
133      * @brief       cec を Ready 状態に移行させます。nn::cec::Initialize() ~ Finalize() の間は呼ぶことはできません。
134                    (暫定的に用意されたAPIです。今後のバージョンでは、cecの状態を直接変更するAPIは削除されます。)
135      * @return      nn::Result
136      */
137     static nn::Result  ReadyDaemon();
138 
139     /*!
140      * @brief       cec の動作を開始させます。
141 
142                     MessageBox::CloseMessageBox の中で、 StartScanning(reset = false) が呼ばれます。
143 
144      * @param[in]   reset         true をセットすると、BOXの内容を読み直して Scan を開始します。<br>
145                                   また、記憶していた通信相手のリストも消去され、同じ相手と再接続することが可能になります。このとき、設定中のボックスだけでなく、全てのボックス(アプリ)のデータが、再度交換される可能性があります。<br>
146                                   デバッグ時等、同じ相手と再接続する必要があるとき以外はtrueにしないでください。<br>
147                                   リストの消去は、nn::cec::CTR::MessageBox::DeleteMessageBox() で BOXを削除したときも行われます。
148 
149      * @return      nn::Result
150      * @retval       ResultSuccess               成功しました。
151      * @retval       ResultStateBusy    Initialize が行われていないなどの理由で動作開始しませんでした。
152      * @retval       上記以外                    失敗しました。
153      */
154     static nn::Result  StartScanning(bool reset = false);
155 
156     /*!
157      :private
158      * @brief       ndmからcecをSuspendさせます。
159 
160      * @return      nn::Result
161      * @retval       ResultSuccess      成功しました。
162      * @retval       ResultStateBusy    停止処理を行いましたが、停止ステートになりませんでした。
163      * @retval       上記以外           失敗しました。
164      */
165     static nn::Result  Suspend();
166 
167     /*!
168      * @brief       cec の動作を手動で停止します。
169 
170                     通信途中だった場合、通信を中断して停止(IDLE)ステータスに移行します。<br>
171                     MessageBox にアクセスするには、停止状態である必要があります。<br>
172                     MessageBox::OpenMessageBox の中で、 StopScanning(b_Immediate = true) が呼ばれます。<br>
173                     事前にこの関数を使用することで、デーモンの動作を中断させず、停止状態になるのを待つことができます。<br><br>
174                     b_Asyncにtrueをセットしたとき、複数回呼んでキャンセルが発生したときなど、この関数から抜けたときに停止ステータスになっていない可能性があります。<br>
175                     この関数を呼んだ後に WriteMessage などを呼んでも、BUSY状態であるためにエラーになる可能性があるので注意してください。
176 
177      * @param[in]   b_Immediate   true をセットすると、通信途中のデータの保存もキャンセルして停止させます。
178      * @param[in]   b_Async   true をセットすると、即座に返ります。
179      * @return      nn::Result
180      * @retval       ResultSuccess      成功しました。
181      * @retval       ResultStateBusy    停止処理を行いましたが、停止ステートになりませんでした。
182      * @retval       上記以外           失敗しました。
183      */
184     static nn::Result  StopScanning(bool b_Immediate = false, bool b_Async = false);
185 
186     /*!
187      :private
188      * @brief       CecDaemon を 停止させます。
189                    (暫定的に用意されたAPIです。今後のバージョンでは、cecの状態を直接変更するAPIは削除されます。)
190 
191                    停止後は StartScanning を呼んでも動作開始しません。
192      * @return      nn::Result
193      */
194     static nn::Result  StopDaemon();
195 
196     /*!
197      :private
198      * @brief       CecDaemon を 動作開始させます。
199                    (暫定的に用意されたAPIです。今後のバージョンでは、cecの状態を直接変更するAPIは削除されます。)
200      * @return      nn::Result
201      */
202     static nn::Result  StartDaemon();
203 
204     /*!
205      :private
206      * @brief       受信したMessageの情報を取得します。
207      * @param[in]   cecTitleId              すれちがい通信ID を指定します。
208      * @param[out]  pCecInfoBuffer          CecNotificationData を受け取るバッファを指定します。
209      * @param[in]   size                    バッファのサイズを指定します。
210      * @return      nn::Result
211      */
212     static nn::Result GetCecInfoBuffer(  u32 cecTitleId, u8 pCecInfoBuffer[], size_t size );
GetCecInfoBuffer(u8 pCecInfoBuffer[],size_t size)213     static nn::Result GetCecInfoBuffer(  u8 pCecInfoBuffer[], size_t size )
214     {
215         return GetCecInfoBuffer(  0, pCecInfoBuffer, size );
216     };
217 
218     /*!
219      * @brief       CECの状態を取得します。
220      * @param[out]  state          状態を示す @ref DaemonState が格納されます。 DAEMON_STATE_IDLE のときのみ、BOXにアクセス可能です。IDLE 以外の状態の遷移は外部から変更できない為、それぞれの状態をハンドリングする必要はありません。
221      * @return      nn::Result
222      * @retval       ResultSuccess      成功しました。
223      */
224     static nn::Result GetCecState( DaemonState* state );
225     static nn::Result GetCecState( u32* state );
226 
227     static bool IsDaemonBusy(void);
228 
229     /*!
230      :private
231      * @brief       受信の通知を受ける Event をセットします。
232      * @param[out]  event          受信があったときに Signal される Event です。
233      * @return      nn::Result
234      */
235     static nn::Result GetCecRecvEventHandle( nn::os::Event* event );
236 
237     static nn::Result GetChangeStateEventHandle( nn::os::Event& event );
238 
239     static nn::cec::CTR::TitleId MakeCecTitleId(bit32 id, bit8 variation = 0x0);
240 
241     /* @brief       NAND上の CECのBOX保存領域をフォーマットします。デバッグ用です。 */
242     static nn::Result FormatSaveData();
243 
244 private:
245     static bool                s_Initialized;
246     static bool                s_NdmSuspended;
247 
248 };
249 
250 
251 
252 
253 //! @name Initialize / Finalize
254 //@{
255 
256 
257 /*!
258  * @brief       CEC Daemon に接続します。CEC MessageBox にアクセスするために最初に呼ぶ必要があります。
259 
260  * @param[in]   cecAllocFunc        CEC ライブラリが使用するアロケータを指定します。
261 
262                                     CEC ライブラリのMessageデータ処理に必要なメモリを確保するために
263                                     使用されます。最大で扱うMessageデータサイズ × 2 程度のメモリが使用されます。
264  * @return      nn::Result
265  */
266 nn::Result  Initialize(nn::fnd::IAllocator& cecAllocFunc);
267 
268 /*!
269  * @brief       CEC Daemon に接続します。CEC MessageBox にアクセスするために最初に呼ぶ必要があります。
270 
271  * @return      nn::Result
272  * @retval       ResultSuccess      成功しました。
273  * @retval       上記以外           失敗しました。
274  */
275 nn::Result  Initialize();
276 
Initialize()277 inline nn::Result  Initialize()
278 {
279     return CecControl::Initialize();
280 }
281 
282 nn::Result  Initialize(nn::cec::CTR::CecAllocFunc& cecAllocFunc);
283 
Initialize(nn::fnd::IAllocator & cecAllocFunc)284 inline nn::Result  Initialize(nn::fnd::IAllocator& cecAllocFunc)
285 {
286     return CecControl::Initialize(cecAllocFunc);
287 }
288 
289 /*!
290  * @brief       CEC Daemon へのアクセスを終了します。
291  * @return      nn::Result
292  * @retval       ResultSuccess      成功しました。
293  * @retval       上記以外           失敗しました。
294  */
295 nn::Result  Finalize();
296 
Finalize()297 inline nn::Result  Finalize()
298 {
299     return CecControl::Finalize();
300 }
301 
302 //@}
303 
304 //! @name 受信通知
305 //@{
306 
307 /*!
308  * @brief       受信の通知を受ける Event を指定します。
309 
310                 すれちがい通信が発生したときにSignalされるEventです。<br>
311                 通信したことをリアルタイムに知りたいときに使用することができます。<br>
312                 フォアグラウンドのアプリケーション宛のデータがあるかどうかは、
313                 @ref GetCecInfoBuffer 等で確認することができます。
314 
315  * @param[out]  event          受信があったときに Signal される Event です。
316  * @return      nn::Result
317  * @retval       ResultSuccess      成功しました。
318  */
319 nn::Result GetCecRecvEventHandle( nn::os::Event* event );
GetCecRecvEventHandle(nn::os::Event * event)320 inline nn::Result GetCecRecvEventHandle( nn::os::Event* event )
321 {
322     return CecControl::GetCecRecvEventHandle( event );
323 }
324 
325 
326 /*!
327  * @brief       直前の通信で受信したMessageの情報を取得します。
328 
329                 @ref GetCecRecvEventHandle を使用して受信の通知を受け取った後、
330                 フォアグラウンドのアプリケーション宛のデータがあるかどうかを調べる時等に使用できます。<br>
331                 グルーピングされた複数のMessageを受け取ったときでも、取得できる情報は1つ分だけです。<br>
332                 また、重複していたために破棄された受信データの情報は入りません。
333 
334   * @param[in]   cecTitleId              すれちがい通信ID を指定します。
335  * @param[out]  pCecInfoBuffer          CecNotificationData を受け取るバッファを指定します。
336  * @param[in]   size                    バッファのサイズを指定します。
337  * @return      nn::Result
338  * @retval       ResultSuccess      成功しました。
339  * @retval       ResultNoData      取得できるデータがありませんでした。
340  */
341 nn::Result GetCecInfoBuffer( u32 cecTitleId, u8 pCecInfoBuffer[], size_t size );
342 nn::Result GetCecInfoBuffer( u8 pCecInfoBuffer[], size_t size );
343 
GetCecInfoBuffer(u32 cecTitleId,u8 pCecInfoBuffer[],size_t size)344 inline nn::Result GetCecInfoBuffer( u32 cecTitleId, u8 pCecInfoBuffer[], size_t size )
345 {
346     return CecControl::GetCecInfoBuffer(cecTitleId, pCecInfoBuffer, size );
347 }
348 
GetCecInfoBuffer(u8 pCecInfoBuffer[],size_t size)349 inline nn::Result GetCecInfoBuffer( u8 pCecInfoBuffer[], size_t size )
350 {
351     return CecControl::GetCecInfoBuffer(0, pCecInfoBuffer, size );
352 }
353 
354 //@}
355 
356 
357 /*!
358   @brief        20bit のユニーク ID から、すれちがい通信で使用する
359                 32bit の すれちがい通信ID(CecTitleId) を生成します。
360 
361   @param[in]    id      20bit の ユニークID です。複数タイトル間で共通のボックスを使用して通信したい場合は、どちらか片方のユニーク ID を指定してください。
362   @param[in]    variation   使用しません。
363  * @return      CecTitleId
364 */
365 nn::cec::CTR::TitleId MakeCecTitleId(bit32 id, bit8 variation = 0x0);
MakeCecTitleId(bit32 id,bit8 variation)366 inline nn::cec::CTR::TitleId MakeCecTitleId(bit32 id, bit8 variation)
367 {
368     return CecControl::MakeCecTitleId(id, variation);
369 }
370 
371 } // end of namespace CTR
372 } // end of namespace cec
373 } // end of namespace nn
374 
375 
376 
377 #endif  // ifndef NN_CEC_CTR_CEC_CONTROL_H_
378