/*---------------------------------------------------------------------------* Project: NintendoWare File: demo_HioPacketChannel.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 16496 $ *---------------------------------------------------------------------------*/ #include namespace nw { namespace demo { const s32 HioPacketChannel::PACKET_HEADER_ID = 0x06F7D144; const size_t HioPacketChannel::BUFFER_SIZE = 1024; void* HioPacketChannel::s_HioWorkMemory = NULL; nw::os::IAllocator* HioPacketChannel::s_DeviceAllocatorForHioWorkMemory = NULL; //--------------------------------------------- HioPacketChannel* HioPacketChannel::Builder::Create( os::IAllocator* allocator, os::IAllocator* deviceAllocator ) { NW_POINTER_ASSERT(allocator); NW_POINTER_ASSERT(deviceAllocator); void* memory = allocator->Alloc(sizeof(HioPacketChannel)); NW_POINTER_ASSERT(memory); HioPacketChannel* hioPacketChannel = new(memory) HioPacketChannel(allocator, deviceAllocator, m_Description); return hioPacketChannel; } //--------------------------------------------- void HioPacketChannel::Destroy() { os::IAllocator* allocator = m_Allocator; this->~HioPacketChannel(); allocator->Free(this); } //--------------------------------------------- bool HioPacketChannel::Initialize(os::IAllocator* deviceAllocator) { s_DeviceAllocatorForHioWorkMemory = deviceAllocator; s_HioWorkMemory = s_DeviceAllocatorForHioWorkMemory->Alloc(nn::hio::CTR::WORKMEMORY_SIZE); return nn::hio::CTR::Initialize(s_HioWorkMemory).IsSuccess(); } //--------------------------------------------- void HioPacketChannel::Finalize() { nn::hio::CTR::Finalize(); s_DeviceAllocatorForHioWorkMemory->Free(s_HioWorkMemory); } //--------------------------------------------- bool HioPacketChannel::Listen(s32 timeOut) { NW_ASSERT(timeOut <= 0); nn::Result result; if (timeOut < 0) { result = m_Serial.WaitHost(nn::hio::CTR::SerialChannel::ATTRIBUTE_NONE); } else { result = m_Serial.WaitHost(nn::hio::CTR::SerialChannel::ATTRIBUTE_NO_WAIT); } return result == nn::hio::CTR::ResultConnected(); } //--------------------------------------------- bool HioPacketChannel::Connect() { return m_Serial.Connect().IsSuccess(); } //--------------------------------------------- bool HioPacketChannel::Disconnect() { return m_Serial.Disconnect().IsSuccess(); } //--------------------------------------------- size_t HioPacketChannel::SendPacket( const void* headerBuffer, size_t headerLength, const void* dataBuffer, size_t dataLength ) { nn::Result result; size_t writtenSize; size_t totalSize = 0; u32 size; // パケットヘッダ ID を送信します。 result = m_Serial.Write(&writtenSize, &PACKET_HEADER_ID, sizeof(PACKET_HEADER_ID)); totalSize += writtenSize; if ( result.IsFailure() || writtenSize != sizeof(PACKET_HEADER_ID) ) { NW_DEV_LOG("SendPacket() : Failed to send packet\n"); return 0; } // ヘッダサイズを送信します。 size = headerLength; result = m_Serial.Write(&writtenSize, &size, sizeof(size)); totalSize += writtenSize; if ( result.IsFailure() || writtenSize != sizeof(size) ) { NW_DEV_LOG("SendPacket() : Failed to send packet\n"); return 0; } // ヘッダを送信します。 if (headerLength) { result = m_Serial.Write(&writtenSize, headerBuffer, headerLength); totalSize += writtenSize; if ( result.IsFailure() || writtenSize != headerLength ) { NW_DEV_LOG("SendPacket() : Failed to send packet\n"); return 0; } } // データサイズを送信します。 size = dataLength; result = m_Serial.Write(&writtenSize, &size, sizeof(size)); totalSize += writtenSize; if ( result.IsFailure() || writtenSize != sizeof(size) ) { NW_DEV_LOG("SendPacket() : Failed to send packet\n"); return 0; } // データを送信します。 if (dataLength) { result = m_Serial.Write(&writtenSize, dataBuffer, dataLength); totalSize += writtenSize; if ( result.IsFailure() || writtenSize != dataLength ) { NW_DEV_LOG("SendPacket() : Failed to send packet\n"); return 0; } } m_Serial.Flush(); return totalSize; } //--------------------------------------------- bool HioPacketChannel::ReceivePacket( size_t* headerWrittenSize, size_t* dataWrittenSize, void* headerBuffer, size_t headerLength, void* dataBuffer, size_t dataLength, int timeOut ) { NW_POINTER_ASSERT(headerWrittenSize); NW_POINTER_ASSERT(dataWrittenSize); s32 headerId = 0; bit32 attr = timeOut < 0 ? nn::hio::CTR::SerialChannel::ATTRIBUTE_NONE : nn::hio::CTR::SerialChannel::ATTRIBUTE_NO_WAIT; int readSize; int size; int totalReadSize; char intBuffer[4]; // パケットヘッダ ID を確認します。 totalReadSize = 0; size = sizeof(s32); do { readSize = m_Serial.Read(intBuffer + totalReadSize, size, attr); if (readSize > 0) { totalReadSize += readSize; size -= readSize; } } while ( size > 0 ); headerId = *reinterpret_cast(intBuffer); if (headerId != PACKET_HEADER_ID) { return false; } // ヘッダのサイズを取得します。 totalReadSize = 0; size = sizeof(s32); do { readSize = m_Serial.Read(intBuffer + totalReadSize, size, attr); if (readSize > 0) { totalReadSize += readSize; size -= readSize; } } while ( size > 0 ); size = *reinterpret_cast(intBuffer); if (headerLength < size) { return false; } *headerWrittenSize = size; // ヘッダを取得します。 totalReadSize = 0; while ( size > 0 ) { NW_POINTER_ASSERT(headerBuffer); readSize = m_Serial.Read( reinterpret_cast(headerBuffer) + totalReadSize, size, attr ); if (readSize > 0) { totalReadSize += readSize; size -= readSize; } }; // データのサイズを取得します。 totalReadSize = 0; size = sizeof(s32); do { readSize = m_Serial.Read(intBuffer + totalReadSize, size, attr); if (readSize > 0) { totalReadSize += readSize; size -= readSize; } } while ( size > 0 ); size = *reinterpret_cast(intBuffer); if (dataLength < size) { return false; } *dataWrittenSize = size; // データを取得します。 totalReadSize = 0; while ( size > 0 ) { NW_POINTER_ASSERT(dataBuffer); readSize = m_Serial.Read( reinterpret_cast(dataBuffer) + totalReadSize, size, attr ); if (readSize > 0) { totalReadSize += readSize; size -= readSize; } }; return true; } //--------------------------------------------- HioPacketChannel::HioPacketChannel( os::IAllocator* allocator, os::IAllocator* deviceAllocator, const Description& description ) : m_Allocator(allocator), m_DeviceAllocator(deviceAllocator) { m_SerialWorkMemory = m_DeviceAllocator->Alloc(nn::hio::CTR::WORKMEMORY_SIZE); nn::Result result = m_Serial.Open(description.channelNumber, m_SerialWorkMemory); NW_ASSERT(result.IsSuccess()); } //--------------------------------------------- HioPacketChannel::~HioPacketChannel() { m_Serial.Close(); m_DeviceAllocator->Free(m_SerialWorkMemory); } } // namespace nw::dev } // namespace nw