1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: demo_HioPacketChannel.cpp
4
5 Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain proprietary
8 information of Nintendo and/or its licensed developers and are protected by
9 national and international copyright laws. They may not be disclosed to third
10 parties or copied or duplicated in any form, in whole or in part, without the
11 prior written consent of Nintendo.
12
13 The content herein is highly confidential and should be handled accordingly.
14
15 $Revision: $
16 *---------------------------------------------------------------------------*/
17
18 #include <nw/demo/demo_HioPacketChannel.h>
19
20 namespace nw
21 {
22
23 namespace demo
24 {
25
26 const s32 HioPacketChannel::PACKET_HEADER_ID = 0x06F7D144;
27 const size_t HioPacketChannel::BUFFER_SIZE = 1024;
28 void* HioPacketChannel::s_HioWorkMemory = NULL;
29 nw::os::IAllocator* HioPacketChannel::s_DeviceAllocatorForHioWorkMemory = NULL;
30
31 //---------------------------------------------
32 HioPacketChannel*
Create(os::IAllocator * allocator,os::IAllocator * deviceAllocator)33 HioPacketChannel::Builder::Create(
34 os::IAllocator* allocator,
35 os::IAllocator* deviceAllocator
36 )
37 {
38 NW_POINTER_ASSERT(allocator);
39 NW_POINTER_ASSERT(deviceAllocator);
40
41 void* memory = allocator->Alloc(sizeof(HioPacketChannel));
42 NW_POINTER_ASSERT(memory);
43
44 HioPacketChannel* hioPacketChannel =
45 new(memory) HioPacketChannel(allocator, deviceAllocator, m_Description);
46
47 return hioPacketChannel;
48 }
49
50 //---------------------------------------------
51 void
Destroy()52 HioPacketChannel::Destroy()
53 {
54 os::IAllocator* allocator = m_Allocator;
55
56 this->~HioPacketChannel();
57 allocator->Free(this);
58
59 }
60
61 //---------------------------------------------
62 bool
Initialize(os::IAllocator * deviceAllocator)63 HioPacketChannel::Initialize(os::IAllocator* deviceAllocator)
64 {
65 s_DeviceAllocatorForHioWorkMemory = deviceAllocator;
66 s_HioWorkMemory = s_DeviceAllocatorForHioWorkMemory->Alloc(nn::hio::CTR::WORKMEMORY_SIZE);
67
68 return nn::hio::CTR::Initialize(s_HioWorkMemory).IsSuccess();
69 }
70
71 //---------------------------------------------
72 void
Finalize()73 HioPacketChannel::Finalize()
74 {
75 nn::hio::CTR::Finalize();
76 s_DeviceAllocatorForHioWorkMemory->Free(s_HioWorkMemory);
77 }
78
79 //---------------------------------------------
80 bool
Listen(s32 timeOut)81 HioPacketChannel::Listen(s32 timeOut)
82 {
83 NW_ASSERT(timeOut <= 0);
84
85 nn::Result result;
86 if (timeOut < 0)
87 {
88 result = m_Serial.WaitHost(nn::hio::CTR::SerialChannel::ATTRIBUTE_NONE);
89 }
90 else
91 {
92 result = m_Serial.WaitHost(nn::hio::CTR::SerialChannel::ATTRIBUTE_NO_WAIT);
93 }
94
95 return result == nn::hio::CTR::ResultConnected();
96 }
97
98 //---------------------------------------------
99 bool
Connect()100 HioPacketChannel::Connect()
101 {
102 return m_Serial.Connect().IsSuccess();
103 }
104
105 //---------------------------------------------
106 bool
Disconnect()107 HioPacketChannel::Disconnect()
108 {
109 return m_Serial.Disconnect().IsSuccess();
110 }
111
112 //---------------------------------------------
113 size_t
SendPacket(const void * headerBuffer,size_t headerLength,const void * dataBuffer,size_t dataLength)114 HioPacketChannel::SendPacket(
115 const void* headerBuffer,
116 size_t headerLength,
117 const void* dataBuffer,
118 size_t dataLength
119 )
120 {
121 nn::Result result;
122 size_t writtenSize;
123 size_t totalSize = 0;
124 u32 size;
125
126 // パケットヘッダ ID を送信します。
127 result = m_Serial.Write(&writtenSize, &PACKET_HEADER_ID, sizeof(PACKET_HEADER_ID));
128 totalSize += writtenSize;
129 if ( result.IsFailure() || writtenSize != sizeof(PACKET_HEADER_ID) )
130 {
131 NW_DEV_LOG("SendPacket() : Failed to send packet\n");
132 return 0;
133 }
134
135 // ヘッダサイズを送信します。
136 size = headerLength;
137 result = m_Serial.Write(&writtenSize, &size, sizeof(size));
138 totalSize += writtenSize;
139 if ( result.IsFailure() || writtenSize != sizeof(size) )
140 {
141 NW_DEV_LOG("SendPacket() : Failed to send packet\n");
142 return 0;
143 }
144
145 // ヘッダを送信します。
146 if (headerLength)
147 {
148 result = m_Serial.Write(&writtenSize, headerBuffer, headerLength);
149 totalSize += writtenSize;
150 if ( result.IsFailure() || writtenSize != headerLength )
151 {
152 NW_DEV_LOG("SendPacket() : Failed to send packet\n");
153 return 0;
154 }
155 }
156
157 // データサイズを送信します。
158 size = dataLength;
159 result = m_Serial.Write(&writtenSize, &size, sizeof(size));
160 totalSize += writtenSize;
161 if ( result.IsFailure() || writtenSize != sizeof(size) )
162 {
163 NW_DEV_LOG("SendPacket() : Failed to send packet\n");
164 return 0;
165 }
166
167 // データを送信します。
168 if (dataLength)
169 {
170 result = m_Serial.Write(&writtenSize, dataBuffer, dataLength);
171 totalSize += writtenSize;
172 if ( result.IsFailure() || writtenSize != dataLength )
173 {
174 NW_DEV_LOG("SendPacket() : Failed to send packet\n");
175 return 0;
176 }
177 }
178
179 m_Serial.Flush();
180
181 return totalSize;
182 }
183
184 //---------------------------------------------
185 bool
ReceivePacket(size_t * headerWrittenSize,size_t * dataWrittenSize,void * headerBuffer,size_t headerLength,void * dataBuffer,size_t dataLength,int timeOut)186 HioPacketChannel::ReceivePacket(
187 size_t* headerWrittenSize,
188 size_t* dataWrittenSize,
189 void* headerBuffer,
190 size_t headerLength,
191 void* dataBuffer,
192 size_t dataLength,
193 int timeOut
194 )
195 {
196 NW_POINTER_ASSERT(headerWrittenSize);
197 NW_POINTER_ASSERT(dataWrittenSize);
198
199 s32 headerId = 0;
200
201 bit32 attr = timeOut < 0 ?
202 nn::hio::CTR::SerialChannel::ATTRIBUTE_NONE :
203 nn::hio::CTR::SerialChannel::ATTRIBUTE_NO_WAIT;
204
205 int readSize;
206 int size;
207 int totalReadSize;
208
209 char intBuffer[4];
210
211 // パケットヘッダ ID を確認します。
212 totalReadSize = 0;
213 size = sizeof(s32);
214 do
215 {
216 readSize = m_Serial.Read(intBuffer + totalReadSize, size, attr);
217 if (readSize > 0)
218 {
219 totalReadSize += readSize;
220 size -= readSize;
221 }
222 } while ( size > 0 );
223 headerId = *reinterpret_cast<s32*>(intBuffer);
224
225 if (headerId != PACKET_HEADER_ID)
226 {
227 return false;
228 }
229
230 // ヘッダのサイズを取得します。
231 totalReadSize = 0;
232 size = sizeof(s32);
233 do
234 {
235 readSize = m_Serial.Read(intBuffer + totalReadSize, size, attr);
236 if (readSize > 0)
237 {
238 totalReadSize += readSize;
239 size -= readSize;
240 }
241 } while ( size > 0 );
242 size = *reinterpret_cast<s32*>(intBuffer);
243
244 if (headerLength < size)
245 {
246 return false;
247 }
248 *headerWrittenSize = size;
249
250 // ヘッダを取得します。
251 totalReadSize = 0;
252 while ( size > 0 )
253 {
254 NW_POINTER_ASSERT(headerBuffer);
255 readSize = m_Serial.Read(
256 reinterpret_cast<char*>(headerBuffer) + totalReadSize,
257 size,
258 attr
259 );
260 if (readSize > 0)
261 {
262 totalReadSize += readSize;
263 size -= readSize;
264 }
265 };
266
267 // データのサイズを取得します。
268 totalReadSize = 0;
269 size = sizeof(s32);
270 do
271 {
272 readSize = m_Serial.Read(intBuffer + totalReadSize, size, attr);
273 if (readSize > 0)
274 {
275 totalReadSize += readSize;
276 size -= readSize;
277 }
278 } while ( size > 0 );
279 size = *reinterpret_cast<s32*>(intBuffer);
280 if (dataLength < size)
281 {
282 return false;
283 }
284 *dataWrittenSize = size;
285
286 // データを取得します。
287 totalReadSize = 0;
288 while ( size > 0 )
289 {
290 NW_POINTER_ASSERT(dataBuffer);
291 readSize = m_Serial.Read(
292 reinterpret_cast<char*>(dataBuffer) + totalReadSize,
293 size,
294 attr
295 );
296 if (readSize > 0)
297 {
298 totalReadSize += readSize;
299 size -= readSize;
300 }
301 };
302
303 return true;
304 }
305
306 //---------------------------------------------
HioPacketChannel(os::IAllocator * allocator,os::IAllocator * deviceAllocator,const Description & description)307 HioPacketChannel::HioPacketChannel(
308 os::IAllocator* allocator,
309 os::IAllocator* deviceAllocator,
310 const Description& description
311 )
312 : m_Allocator(allocator),
313 m_DeviceAllocator(deviceAllocator)
314 {
315 m_SerialWorkMemory = m_DeviceAllocator->Alloc(nn::hio::CTR::WORKMEMORY_SIZE);
316
317 nn::Result result = m_Serial.Open(description.channelNumber, m_SerialWorkMemory);
318
319 NW_ASSERT(result.IsSuccess());
320 }
321
322 //---------------------------------------------
~HioPacketChannel()323 HioPacketChannel::~HioPacketChannel()
324 {
325 m_Serial.Close();
326 m_DeviceAllocator->Free(m_SerialWorkMemory);
327 }
328
329
330
331 } // namespace nw::dev
332 } // namespace nw
333
334