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