193 lines
5.6 KiB
C++
193 lines
5.6 KiB
C++
#pragma once
|
|
|
|
#include <gear.h>
|
|
#include <revolution/hio2.h>
|
|
|
|
// RULE FOR MOST APPL
|
|
// RESERVE 1024 first bytes FROM NDEV
|
|
// RESERVE the following 1024 bytes TO NDEV
|
|
#define GEAR_NDEVWIIMOTE_HIO2_DATAADDR_FROM_NDEV 0
|
|
#define GEAR_NDEVWIIMOTE_HIO2_DATAADDR_TO_NDEV GEAR_KB(1)
|
|
|
|
// Id of message sent from the NDEV
|
|
#define GEAR_NDEVWIIMOTE_HIO2_FROM_NDEV 4501
|
|
// Id of message sent to the NDEV
|
|
#define GEAR_NDEVWIIMOTE_HIO2_TO_NDEV 4502
|
|
|
|
#define GEAR_NDEVWIIMOTE_TIMEOUT_SEC 5
|
|
|
|
// Singleton
|
|
// Start HIO2, ConnectionThread, StatusThread
|
|
// Act as a server which a PC application can connect and get data from a connected NDEV
|
|
// with HIO2. With the HIO2 callback it receive information and sent it back to the PC via TCP.
|
|
class Hio2Proxy
|
|
{
|
|
public:
|
|
|
|
static inline Hio2Proxy* GetInstance()
|
|
{
|
|
if (!m_Instance)
|
|
{
|
|
m_Instance = GEAR_ALLOC(Hio2Proxy, 1, GEAR_NS::DefaultAllocator(), 0, "Hio2Proxy");
|
|
new(m_Instance) Hio2Proxy;
|
|
}
|
|
|
|
return m_Instance;
|
|
}
|
|
|
|
static inline void Shutdown()
|
|
{
|
|
if (m_Instance)
|
|
{
|
|
m_Instance->~Hio2Proxy();
|
|
GEAR_FREE(m_Instance);
|
|
}
|
|
}
|
|
|
|
inline GEAR_NS::Bool GetFinish()
|
|
{
|
|
// Error or finish message from either one of these trigger the end of the application.
|
|
return m_Finish || m_ConnectionThread.IsFinish();
|
|
}
|
|
|
|
inline HIO2Handle GetHandle()
|
|
{
|
|
return m_Handle;
|
|
}
|
|
|
|
inline void SetConnectionPort(GEAR_NS::U16 port)
|
|
{
|
|
m_ConnectionThread.SetPort(port);
|
|
}
|
|
|
|
// Init thread and HIO2
|
|
void Init();
|
|
|
|
void SetDevice(HIO2DevicePath device);
|
|
void Receive(HIO2Handle handle);
|
|
void UpdateStatus();
|
|
|
|
// HIO2 Callbacks
|
|
static BOOL __hio2EnumDevicesCB( HIO2DevicePath pathName, LPVOID param );
|
|
static void __hio2ReceiveCB( HIO2Handle handle );
|
|
static int __hio2NotifyCB( HIO2NotifyEvent event, LPVOID param );
|
|
|
|
private:
|
|
|
|
// This is the server thread which a PC application can connect.
|
|
class ConnectionThread : public GEAR_NS::Thread
|
|
{
|
|
public:
|
|
ConnectionThread();
|
|
~ConnectionThread();
|
|
|
|
virtual void Run();
|
|
|
|
// Basic TCP send
|
|
GEAR_NS::Bool Send(const GEAR_NS::Char* buffer, GEAR_NS::U32 len)
|
|
{
|
|
if (m_ClientSocket)
|
|
{
|
|
GEAR_NS::S32 bytesSent = m_ClientSocket->Send(buffer, len);
|
|
|
|
if (m_ClientSocket->GetError() != GEAR_NS::Socket::EOk &&
|
|
m_ClientSocket->GetError() != GEAR_NS::Socket::ETimedOut &&
|
|
m_ClientSocket->GetError() != GEAR_NS::Socket::EWouldBlock)
|
|
return GEAR_NS::False;
|
|
|
|
if (bytesSent < 0)
|
|
return GEAR_NS::False;
|
|
|
|
return GEAR_NS::True;
|
|
}
|
|
|
|
return GEAR_NS::False;
|
|
}
|
|
|
|
inline GEAR_NS::Bool IsConnected()
|
|
{
|
|
return m_IsConnected;
|
|
}
|
|
|
|
inline GEAR_NS::Bool IsFinish()
|
|
{
|
|
return m_Finish;
|
|
}
|
|
|
|
inline void SetFinish()
|
|
{
|
|
m_Finish = GEAR_NS::True;
|
|
}
|
|
|
|
inline void SetPort(GEAR_NS::U16 port)
|
|
{
|
|
m_Port = port;
|
|
}
|
|
|
|
private:
|
|
|
|
GEAR_NS::Bool m_IsConnected;
|
|
GEAR_NS::Bool m_Finish;
|
|
GEAR_NS::TcpSocket m_ServerSocket;
|
|
GEAR_NS::TcpSocket* m_ClientSocket;
|
|
GEAR_NS::Char* m_WriteBuffer;
|
|
GEAR_NS::U16 m_Port;
|
|
};
|
|
|
|
// Because HIO2 is not a so great library we need to have a thread
|
|
// that read the HIO2 mailbox constantly when where not connected.
|
|
// That way if the NDEV write mailbox and there nobody to read it
|
|
// it will not fill the mailbox yeilding to many error on the NDEV
|
|
// side.
|
|
class StatusThread : public GEAR_NS::Thread
|
|
{
|
|
public:
|
|
inline StatusThread() : m_Finish(GEAR_NS::False) {}
|
|
inline ~StatusThread() {}
|
|
|
|
virtual void Run();
|
|
|
|
inline GEAR_NS::Bool IsFinish()
|
|
{
|
|
return m_Finish;
|
|
}
|
|
|
|
inline void SetFinish()
|
|
{
|
|
m_Finish = GEAR_NS::True;
|
|
}
|
|
|
|
private:
|
|
GEAR_NS::Bool m_Finish;
|
|
};
|
|
|
|
private:
|
|
|
|
Hio2Proxy();
|
|
~Hio2Proxy();
|
|
|
|
// Uninit thread and HIO2
|
|
void UnInit();
|
|
|
|
// Basic send to HIO2. Length is the real length, it will be rounded to
|
|
// the next multiple of 32. The data must be after the first 4 bytes of
|
|
// buffer (start at &buffer[sizeof(GEAR_NS::U32)]). Since we will put
|
|
// the length in those first 4 bytes.
|
|
GEAR_NS::Bool SendMessageToNDev(GEAR_NS::Char* buffer, GEAR_NS::U32 length);
|
|
|
|
GEAR_NS::Bool m_Finish;
|
|
|
|
HIO2Handle m_Handle;
|
|
GEAR_NS::GearString m_DevicePath;
|
|
|
|
// 32 bytes align
|
|
GEAR_NS::Char* m_ReceiveBuffer;
|
|
|
|
// last message from the NDEV, for now we will ignore all message except GEAR_NDEVWIIMOTE_HIO2_FROM_NDEV
|
|
u32 m_LastMsg;
|
|
|
|
ConnectionThread m_ConnectionThread;
|
|
StatusThread m_UpdateStatus;
|
|
|
|
static Hio2Proxy* m_Instance;
|
|
};
|