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