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