#pragma once #include #include // 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; };