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: 32865 $
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 <br>
65 通信を行うと、その相手を記憶し、平均 4 時間、最大 8 時間経過するまで再通信しません。<br>
66 相手を記憶するのは、1つ以上のデータの送受信があった場合、通信開始したが送受信すべきデータが無かった場合です。<br>
67 この情報は、電源をOFFにしても保持されます。<br>
68 好きなタイミングで相手にデータを届けるという使い方ができないことに注意してください。<br>
69 デバッグ用として、通信を行った相手の情報をリセットし、同じ相手と再度通信することを可能にする手段が用意されています。StartScanning の引数にtrueを指定することでリセットが行われます。この機能はReleaseビルドでは使用できません。
70 */
71
72 class CecControl {
73
74 public:
75
76 enum ChangeDaemonState{
77 DAEMON_CHANGE_STATE_READY ,
78 DAEMON_CHANGE_STATE_STARTSCAN ,
79 DAEMON_CHANGE_STATE_STOP,
80 DAEMON_CHANGE_STATE_STOP_DAEMON,
81 DAEMON_CHANGE_STATE_START_DAEMON,
82 DAEMON_CHANGE_STATE_RESET_FILTER,
83
84 DAEMON_CHANGE_STATE_NDM_RESUME,
85 DAEMON_CHANGE_STATE_NDM_SUSPEND
86
87 };
88
89 /*!
90 @brief @ref GetCecState で取得される、Cecの状態を示す値です。DAEMON_STATE_IDLE のときしか BOXにアクセスすることはできません。
91 */
92 enum DaemonState
93 {
94 DAEMON_STATE_STOP, //!< 動作していません
95 DAEMON_STATE_IDLE, //!< 停止中
96 DAEMON_STATE_BUSY, //!< 処理中
97 DAEMON_STATE_SCAN, //!< スキャン中
98 DAEMON_STATE_READY, //!< READY状態(インターネット通信など、別の通信をしており、すれちがい通信に入っていない状態)
99 DAEMON_STATE_COMMUNICATING //!< 通信中
100 };
101
102
103 CecControl(size_t bufSize);
104 CecControl();
105 ~CecControl();
106
107 /*!
108 :private
109 * @brief cec に接続します。cec にアクセスするために最初に呼ぶ必要があります。
110 * @return nn::Result
111 */
112 static nn::Result Initialize();
113 //static nn::Result Initialize(CecAllocFunc& cecAllocFunc);
114 static nn::Result Initialize(nn::fnd::IAllocator& cecAllocFunc);
115 #if 0
116 static nn::Result InitializeSys();
117 #endif
118
119 /*!
120 :private
121 * @brief cec へのアクセスを終了します。
122 * @return nn::Result
123 */
124 static nn::Result Finalize();
125
126 #if 0
127 static nn::Result FinalizeSys();
128 #endif
129
130
131 static bool IsInitialized();
132 #if 0
133 static bool IsInitializedSys();
134 #endif
135
136 /*!
137 :private
138 * @brief cec を Ready 状態に移行させます。nn::cec::Initialize() ~ Finalize() の間は呼ぶことはできません。
139 (暫定的に用意されたAPIです。今後のバージョンでは、cecの状態を直接変更するAPIは削除されます。)
140 * @return nn::Result
141 */
142 static nn::Result ReadyDaemon();
143
144 /*!
145 * @brief cec の動作を開始させます。
146
147 MessageBox::CloseMessageBox の中で、 StartScanning(reset = false) が呼ばれます。
148
149 * @param[in] reset true をセットすると、BOXの内容を読み直して Scan を開始します。<br>
150 また、記憶していた通信相手のリストも消去され、同じ相手と再接続することが可能になります。このとき、設定中のボックスだけでなく、全てのボックス(アプリ)のデータが、再度交換される可能性があります。<br>
151 Releaseビルドでは true に設定してもリセット動作は行われませんのでご注意ください。
152
153 * @return nn::Result
154 * @retval ResultSuccess 成功しました。
155 * @retval ResultStateBusy Initialize が行われていないなどの理由で動作開始しませんでした。
156 * @retval 上記以外 失敗しました。
157 */
158 static nn::Result StartScanning(bool reset = false);
159
160 /*!
161 :private
162 * @brief ndmからcecをSuspendさせます。
163
164 * @return nn::Result
165 * @retval ResultSuccess 成功しました。
166 * @retval ResultStateBusy 停止処理を行いましたが、停止ステートになりませんでした。
167 * @retval 上記以外 失敗しました。
168 */
169 static nn::Result Suspend();
170
171 /*!
172 * @brief cec の動作を手動で停止します。
173
174 通信途中だった場合、通信を中断して停止(IDLE)ステータスに移行します。<br>
175 MessageBox にアクセスするには、停止状態である必要があります。<br>
176 MessageBox::OpenMessageBox の中で、 StopScanning(b_Immediate = true) が呼ばれます。<br>
177 事前にこの関数を使用することで、デーモンの動作を中断させず、停止状態になるのを待つことができます。<br><br>
178 b_Asyncにtrueをセットしたとき、複数回呼んでキャンセルが発生したときなど、この関数から抜けたときに停止ステータスになっていない可能性があります。<br>
179 この関数を呼んだ後に WriteMessage などを呼んでも、BUSY状態であるためにエラーになる可能性があるので注意してください。
180
181 * @param[in] b_Immediate true をセットすると、通信途中のデータの保存もキャンセルして停止させます。
182 * @param[in] b_Async true をセットすると、即座に返ります。
183 * @return nn::Result
184 * @retval ResultSuccess 成功しました。
185 * @retval ResultStateBusy 停止処理を行いましたが、停止ステートになりませんでした。
186 * @retval 上記以外 失敗しました。
187 */
188 static nn::Result StopScanning(bool b_Immediate = false, bool b_Async = false);
189
190 /*!
191 :private
192 * @brief CecDaemon を 停止させます。
193 (暫定的に用意されたAPIです。今後のバージョンでは、cecの状態を直接変更するAPIは削除されます。)
194
195 停止後は StartScanning を呼んでも動作開始しません。
196 * @return nn::Result
197 */
198 static nn::Result StopDaemon();
199
200 /*!
201 :private
202 * @brief CecDaemon を 動作開始させます。
203 (暫定的に用意されたAPIです。今後のバージョンでは、cecの状態を直接変更するAPIは削除されます。)
204 * @return nn::Result
205 */
206 static nn::Result StartDaemon();
207
208 /*!
209 :private
210 * @brief 受信したMessageの情報を取得します。
211 * @param[in] cecTitleId すれちがい通信ID を指定します。
212 * @param[out] pCecInfoBuffer CecNotificationData を受け取るバッファを指定します。
213 * @param[in] size バッファのサイズを指定します。
214 * @return nn::Result
215 */
216 static nn::Result GetCecInfoBuffer( u32 cecTitleId, u8 pCecInfoBuffer[], size_t size );
GetCecInfoBuffer(u8 pCecInfoBuffer[],size_t size)217 static nn::Result GetCecInfoBuffer( u8 pCecInfoBuffer[], size_t size )
218 {
219 return GetCecInfoBuffer( 0, pCecInfoBuffer, size );
220 };
221
222 /*!
223 * @brief CECの状態を取得します。
224 * @param[out] state 状態を示す @ref DaemonState が格納されます。 DAEMON_STATE_IDLE のときのみ、BOXにアクセス可能です。IDLE 以外の状態の遷移は外部から変更できない為、それぞれの状態をハンドリングする必要はありません。
225 * @return nn::Result
226 * @retval ResultSuccess 成功しました。
227 */
228 static nn::Result GetCecState( DaemonState* state );
229 static nn::Result GetCecState( u32* state );
230
231 static bool IsDaemonBusy(void);
232
233 /*!
234 :private
235 * @brief 受信の通知を受ける Event をセットします。
236 * @param[out] event 受信があったときに Signal される Event です。
237 * @return nn::Result
238 */
239 static nn::Result GetCecRecvEventHandle( nn::os::Event* event );
240
241 static nn::Result GetChangeStateEventHandle( nn::os::Event& event );
242
243 static nn::cec::CTR::TitleId MakeCecTitleId(bit32 id, bit8 variation = 0x0);
244
245 /* @brief NAND上の CECのBOX保存領域をフォーマットします。デバッグ用です。 */
246 static nn::Result FormatSaveData();
247
248 /*!
249 :private
250 * @brief 排他モードに入ります。(デバッグ用)
251 バックグラウンド通信をすれちがい通信専用にします。<br>
252 他のプロセスが既に排他モードに切り替えていたとき、ローカル通信を行っているときはエラーとなります。<br>
253 排他モードを終えるときは LeaveExclusiveState を呼んでください。<br>
254
255 ※ システムの通信ポリシーを変更してしまう API ですので、デバッグ用途のみの利用に限定し、製品版に組み込まれることが無いようにしてください。
256
257 * @return nn::Result
258 */
259 static nn::Result EnterExclusiveState();
260
261 /*!
262 :private
263 * @brief 排他モードを終了します。(デバッグ用)
264 * @return nn::Result
265 */
266 static nn::Result LeaveExclusiveState();
267
268 private:
269 static bool s_Initialized;
270 static bool s_NdmSuspended;
271 static bool s_EnterExclusiveState;
272 static nn::os::CriticalSection m_Cs;
273
274 };
275
276
277
278
279 //! @name Initialize / Finalize
280 //@{
281
282
283 /*!
284 * @brief CEC Daemon に接続します。CEC MessageBox にアクセスするために最初に呼ぶ必要があります。
285
286 * @param[in] cecAllocFunc CEC ライブラリが使用するアロケータを指定します。
287
288 CEC ライブラリのMessageデータ処理に必要なメモリを確保するために
289 使用されます。最大で扱うMessageデータサイズ × 2 程度のメモリが使用されます。
290 * @return nn::Result
291 */
292 nn::Result Initialize(nn::fnd::IAllocator& cecAllocFunc);
293
294 /*!
295 * @brief CEC Daemon に接続します。CEC MessageBox にアクセスするために最初に呼ぶ必要があります。
296
297 * @return nn::Result
298 * @retval ResultSuccess 成功しました。
299 * @retval 上記以外 失敗しました。
300 */
301 nn::Result Initialize();
302
Initialize()303 inline nn::Result Initialize()
304 {
305 return CecControl::Initialize();
306 }
307
308 nn::Result Initialize(nn::cec::CTR::CecAllocFunc& cecAllocFunc);
309
Initialize(nn::fnd::IAllocator & cecAllocFunc)310 inline nn::Result Initialize(nn::fnd::IAllocator& cecAllocFunc)
311 {
312 return CecControl::Initialize(cecAllocFunc);
313 }
314
315 /*!
316 * @brief CEC Daemon へのアクセスを終了します。
317 * @return nn::Result
318 * @retval ResultSuccess 成功しました。
319 * @retval 上記以外 失敗しました。
320 */
321 nn::Result Finalize();
322
Finalize()323 inline nn::Result Finalize()
324 {
325 return CecControl::Finalize();
326 }
327
328 //@}
329
330 //! @name 受信通知
331 //@{
332
333 /*!
334 * @brief 受信の通知を受ける Event を指定します。
335
336 すれちがい通信が発生したときにSignalされるEventです。<br>
337 通信したことをリアルタイムに知りたいときに使用することができます。<br>
338 フォアグラウンドのアプリケーション宛のデータがあるかどうかは、
339 @ref GetCecInfoBuffer 等で確認することができます。
340
341 * @param[out] event 受信があったときに Signal される Event です。
342 * @return nn::Result
343 * @retval ResultSuccess 成功しました。
344 */
345 nn::Result GetCecRecvEventHandle( nn::os::Event* event );
GetCecRecvEventHandle(nn::os::Event * event)346 inline nn::Result GetCecRecvEventHandle( nn::os::Event* event )
347 {
348 return CecControl::GetCecRecvEventHandle( event );
349 }
350
351
352 /*!
353 * @brief 直前の通信で受信したMessageの情報を取得します。
354
355 @ref GetCecRecvEventHandle を使用して受信の通知を受け取った後、
356 フォアグラウンドのアプリケーション宛のデータがあるかどうかを調べる時等に使用できます。<br>
357 グルーピングされた複数のMessageを受け取ったときでも、取得できる情報は1つ分だけです。<br>
358 また、重複していたために破棄された受信データの情報は入りません。<br>
359 CecNotificationData のcountの値は、すれちがい通信が発生する度に増加します。
360 この値の変化を調べることで、通信の有無を知ることも可能です。
361
362 * @param[in] cecTitleId すれちがい通信ID を指定します。
363 * @param[out] pCecInfoBuffer CecNotificationData を受け取るバッファを指定します。
364 * @param[in] size バッファのサイズを指定します。
365 * @return nn::Result
366 * @retval ResultSuccess 成功しました。
367 * @retval ResultNoData 取得できるデータがありませんでした。
368 */
369 nn::Result GetCecInfoBuffer( u32 cecTitleId, u8 pCecInfoBuffer[], size_t size );
370 nn::Result GetCecInfoBuffer( u8 pCecInfoBuffer[], size_t size );
371
GetCecInfoBuffer(u32 cecTitleId,u8 pCecInfoBuffer[],size_t size)372 inline nn::Result GetCecInfoBuffer( u32 cecTitleId, u8 pCecInfoBuffer[], size_t size )
373 {
374 return CecControl::GetCecInfoBuffer(cecTitleId, pCecInfoBuffer, size );
375 }
376
GetCecInfoBuffer(u8 pCecInfoBuffer[],size_t size)377 inline nn::Result GetCecInfoBuffer( u8 pCecInfoBuffer[], size_t size )
378 {
379 return CecControl::GetCecInfoBuffer(0, pCecInfoBuffer, size );
380 }
381
382 //@}
383
384
385 /*!
386 @brief 20bit のユニーク ID から、すれちがい通信で使用する
387 32bit の すれちがい通信ID(CecTitleId) を生成します。
388
389 @param[in] id 20bit の ユニークID です。複数タイトル間で共通のボックスを使用して通信したい場合は、どちらか片方のユニーク ID を指定してください。
390 @param[in] variation 使用しません。
391 * @return CecTitleId
392 */
393 nn::cec::CTR::TitleId MakeCecTitleId(bit32 id, bit8 variation = 0x0);
MakeCecTitleId(bit32 id,bit8 variation)394 inline nn::cec::CTR::TitleId MakeCecTitleId(bit32 id, bit8 variation)
395 {
396 return CecControl::MakeCecTitleId(id, variation);
397 }
398
399 } // end of namespace CTR
400 } // end of namespace cec
401 } // end of namespace nn
402
403
404
405 #endif // ifndef NN_CEC_CTR_CEC_CONTROL_H_
406