mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-11 06:59:07 +01:00
commit some crappy threading code for usbgecko
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6870 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
d89d730778
commit
fdd56f4621
@ -17,17 +17,47 @@
|
|||||||
|
|
||||||
#include "EXI_Device.h"
|
#include "EXI_Device.h"
|
||||||
#include "EXI_DeviceGecko.h"
|
#include "EXI_DeviceGecko.h"
|
||||||
|
//#pragma optimize("",off)
|
||||||
|
THREAD_RETURN ClientThreadFunc(void *arg)
|
||||||
|
{
|
||||||
|
((GeckoSockServer*)arg)->ClientThread();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#include "SFML/Network.hpp"
|
int GeckoSockServer::client_count;
|
||||||
#include "Thread.h"
|
Common::Thread *GeckoSockServer::connectionThread = NULL;
|
||||||
#include <queue>
|
volatile bool GeckoSockServer::server_running;
|
||||||
|
std::queue<sf::SocketTCP> GeckoSockServer::waiting_socks;
|
||||||
|
Common::CriticalSection GeckoSockServer::connection_lock;
|
||||||
|
|
||||||
static Common::Thread *connectionThread = NULL;
|
GeckoSockServer::GeckoSockServer()
|
||||||
static std::queue<sf::SocketTCP> waiting_socks;
|
: clientThread(NULL)
|
||||||
static Common::CriticalSection cs_gecko;
|
, client_running(false)
|
||||||
namespace { volatile bool server_running; }
|
{
|
||||||
|
if (!connectionThread)
|
||||||
|
connectionThread = new Common::Thread(&GeckoConnectionWaiter, (void*)0);
|
||||||
|
}
|
||||||
|
|
||||||
static THREAD_RETURN GeckoConnectionWaiter(void*)
|
GeckoSockServer::~GeckoSockServer()
|
||||||
|
{
|
||||||
|
if (client_running)
|
||||||
|
{
|
||||||
|
client_running = false;
|
||||||
|
clientThread->WaitForDeath();
|
||||||
|
}
|
||||||
|
delete clientThread;
|
||||||
|
clientThread = NULL;
|
||||||
|
|
||||||
|
if (--client_count <= 0)
|
||||||
|
{
|
||||||
|
server_running = false;
|
||||||
|
connectionThread->WaitForDeath();
|
||||||
|
delete connectionThread;
|
||||||
|
connectionThread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
THREAD_RETURN GeckoSockServer::GeckoConnectionWaiter(void*)
|
||||||
{
|
{
|
||||||
server_running = true;
|
server_running = true;
|
||||||
|
|
||||||
@ -45,9 +75,9 @@ static THREAD_RETURN GeckoConnectionWaiter(void*)
|
|||||||
{
|
{
|
||||||
if (server.Accept(new_client) == sf::Socket::Done)
|
if (server.Accept(new_client) == sf::Socket::Done)
|
||||||
{
|
{
|
||||||
cs_gecko.Enter();
|
connection_lock.Enter();
|
||||||
waiting_socks.push(new_client);
|
waiting_socks.push(new_client);
|
||||||
cs_gecko.Leave();
|
connection_lock.Leave();
|
||||||
}
|
}
|
||||||
SLEEP(1);
|
SLEEP(1);
|
||||||
}
|
}
|
||||||
@ -55,73 +85,79 @@ static THREAD_RETURN GeckoConnectionWaiter(void*)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeckoConnectionWaiter_Shutdown()
|
bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill)
|
||||||
{
|
|
||||||
server_running = false;
|
|
||||||
if (connectionThread)
|
|
||||||
{
|
|
||||||
connectionThread->WaitForDeath();
|
|
||||||
delete connectionThread;
|
|
||||||
connectionThread = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool GetAvailableSock(sf::SocketTCP& sock_to_fill)
|
|
||||||
{
|
{
|
||||||
bool sock_filled = false;
|
bool sock_filled = false;
|
||||||
|
|
||||||
cs_gecko.Enter();
|
connection_lock.Enter();
|
||||||
if (waiting_socks.size())
|
if (waiting_socks.size())
|
||||||
{
|
{
|
||||||
sock_to_fill = waiting_socks.front();
|
sock_to_fill = waiting_socks.front();
|
||||||
|
if (clientThread)
|
||||||
|
{
|
||||||
|
if (client_running)
|
||||||
|
{
|
||||||
|
client_running = false;
|
||||||
|
clientThread->WaitForDeath();
|
||||||
|
}
|
||||||
|
delete clientThread;
|
||||||
|
clientThread = NULL;
|
||||||
|
}
|
||||||
|
clientThread = new Common::Thread(ClientThreadFunc, this);
|
||||||
|
client_count++;
|
||||||
waiting_socks.pop();
|
waiting_socks.pop();
|
||||||
sock_filled = true;
|
sock_filled = true;
|
||||||
}
|
}
|
||||||
cs_gecko.Leave();
|
connection_lock.Leave();
|
||||||
|
|
||||||
return sock_filled;
|
return sock_filled;
|
||||||
}
|
}
|
||||||
|
|
||||||
GeckoSockServer::GeckoSockServer()
|
void GeckoSockServer::ClientThread()
|
||||||
{
|
{
|
||||||
if (!connectionThread)
|
client_running = true;
|
||||||
connectionThread = new Common::Thread(GeckoConnectionWaiter, (void*)0);
|
|
||||||
}
|
Common::SetCurrentThreadName("Gecko Client");
|
||||||
|
|
||||||
|
client.SetBlocking(false);
|
||||||
|
|
||||||
|
while (client_running)
|
||||||
|
{
|
||||||
|
u8 data;
|
||||||
|
std::size_t got = 0;
|
||||||
|
|
||||||
|
transfer_lock.Enter();
|
||||||
|
if (client.Receive((char*)&data, sizeof(data), got)
|
||||||
|
== sf::Socket::Disconnected)
|
||||||
|
client_running = false;
|
||||||
|
if (got)
|
||||||
|
recv_fifo.push(data);
|
||||||
|
|
||||||
|
if (send_fifo.size())
|
||||||
|
{
|
||||||
|
if (client.Send((char*)&send_fifo.front(), sizeof(u8))
|
||||||
|
== sf::Socket::Disconnected)
|
||||||
|
client_running = false;
|
||||||
|
send_fifo.pop();
|
||||||
|
}
|
||||||
|
transfer_lock.Leave();
|
||||||
|
SLEEP(1);
|
||||||
|
}
|
||||||
|
|
||||||
GeckoSockServer::~GeckoSockServer()
|
|
||||||
{
|
|
||||||
client.Close();
|
client.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
CEXIGecko::CEXIGecko()
|
|
||||||
: m_uPosition(0)
|
|
||||||
, recv_fifo(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CEXIGecko::SetCS(int cs)
|
|
||||||
{
|
|
||||||
if (cs)
|
|
||||||
m_uPosition = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CEXIGecko::IsPresent()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CEXIGecko::ImmReadWrite(u32 &_uData, u32 _uSize)
|
void CEXIGecko::ImmReadWrite(u32 &_uData, u32 _uSize)
|
||||||
{
|
{
|
||||||
|
// We don't really care about _uSize
|
||||||
|
(void)_uSize;
|
||||||
|
|
||||||
if (!client.IsValid())
|
if (!client.IsValid())
|
||||||
if (!GetAvailableSock(client))
|
if (!GetAvailableSock(client))
|
||||||
{} ;// TODO nothing for now
|
return;
|
||||||
|
|
||||||
// for debug
|
// for debug
|
||||||
u32 oldval = _uData;
|
u32 oldval = _uData;
|
||||||
// TODO do we really care about _uSize?
|
|
||||||
|
|
||||||
u8 data = 0;
|
|
||||||
std::size_t got;
|
|
||||||
|
|
||||||
switch (_uData >> 28)
|
switch (_uData >> 28)
|
||||||
{
|
{
|
||||||
@ -130,26 +166,31 @@ void CEXIGecko::ImmReadWrite(u32 &_uData, u32 _uSize)
|
|||||||
break;
|
break;
|
||||||
case CMD_LED_ON:
|
case CMD_LED_ON:
|
||||||
break;
|
break;
|
||||||
// maybe should only | 2bytes?
|
|
||||||
case CMD_INIT:
|
case CMD_INIT:
|
||||||
_uData = ident;
|
_uData = ident;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// PC -> Gecko
|
// PC -> Gecko
|
||||||
|
// |= 0x08000000 if successful
|
||||||
case CMD_RECV:
|
case CMD_RECV:
|
||||||
// TODO recv
|
transfer_lock.Enter();
|
||||||
client.Receive((char*)&data, sizeof(data), got);
|
if (recv_fifo.size())
|
||||||
recv_fifo = !!got;
|
{
|
||||||
if (recv_fifo)
|
_uData = 0x08000000 | (recv_fifo.front() << 16);
|
||||||
_uData = 0x08000000 | (data << 16);
|
recv_fifo.pop();
|
||||||
|
}
|
||||||
|
transfer_lock.Leave();
|
||||||
break;
|
break;
|
||||||
// Gecko -> PC
|
// Gecko -> PC
|
||||||
|
// |= 0x04000000 if successful
|
||||||
case CMD_SEND:
|
case CMD_SEND:
|
||||||
data = (_uData >> 20) & 0xff;
|
transfer_lock.Enter();
|
||||||
// TODO send
|
send_fifo.push(_uData >> 20);
|
||||||
client.Send((char*)&data, sizeof(data));
|
transfer_lock.Leave();
|
||||||
// If successful
|
_uData = 0x04000000;
|
||||||
_uData |= 0x04000000;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Check if ok for Gecko -> PC, or FIFO full
|
// Check if ok for Gecko -> PC, or FIFO full
|
||||||
// |= 0x04000000 if FIFO is not full
|
// |= 0x04000000 if FIFO is not full
|
||||||
case CMD_CHK_TX:
|
case CMD_CHK_TX:
|
||||||
@ -158,13 +199,14 @@ void CEXIGecko::ImmReadWrite(u32 &_uData, u32 _uSize)
|
|||||||
// Check if data in FIFO for PC -> Gecko, or FIFO empty
|
// Check if data in FIFO for PC -> Gecko, or FIFO empty
|
||||||
// |= 0x04000000 if data in recv FIFO
|
// |= 0x04000000 if data in recv FIFO
|
||||||
case CMD_CHK_RX:
|
case CMD_CHK_RX:
|
||||||
//_uData = recv_fifo ? 0x04000000 : 0;
|
transfer_lock.Enter();
|
||||||
_uData = 0x04000000;
|
_uData = recv_fifo.size() ? 0x04000000 : 0;
|
||||||
|
transfer_lock.Leave();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(EXPANSIONINTERFACE, "Uknown USBGecko command %x", _uData);
|
ERROR_LOG(EXPANSIONINTERFACE, "Uknown USBGecko command %x", _uData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_uData) { ERROR_LOG(EXPANSIONINTERFACE, "rw %x %08x %08x", oldval, _uData, _uSize); }
|
|
||||||
}
|
}
|
||||||
|
//#pragma optimize("",on)
|
@ -19,6 +19,8 @@
|
|||||||
#define _EXIDEVICE_GECKO_H
|
#define _EXIDEVICE_GECKO_H
|
||||||
|
|
||||||
#include "SFML/Network.hpp"
|
#include "SFML/Network.hpp"
|
||||||
|
#include "Thread.h"
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
class GeckoSockServer
|
class GeckoSockServer
|
||||||
: public sf::SocketTCP
|
: public sf::SocketTCP
|
||||||
@ -26,9 +28,28 @@ class GeckoSockServer
|
|||||||
public:
|
public:
|
||||||
GeckoSockServer();
|
GeckoSockServer();
|
||||||
~GeckoSockServer();
|
~GeckoSockServer();
|
||||||
|
bool GetAvailableSock(sf::SocketTCP &sock_to_fill);
|
||||||
|
|
||||||
//private:
|
// Client for this server object
|
||||||
sf::SocketTCP client;
|
sf::SocketTCP client;
|
||||||
|
void ClientThread();
|
||||||
|
Common::Thread *clientThread;
|
||||||
|
Common::CriticalSection transfer_lock;
|
||||||
|
|
||||||
|
std::queue<u8> send_fifo;
|
||||||
|
std::queue<u8> recv_fifo;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int client_count;
|
||||||
|
volatile bool client_running;
|
||||||
|
|
||||||
|
// Only ever one server thread
|
||||||
|
static THREAD_RETURN GeckoConnectionWaiter(void*);
|
||||||
|
|
||||||
|
static volatile bool server_running;
|
||||||
|
static Common::Thread *connectionThread;
|
||||||
|
static std::queue<sf::SocketTCP> waiting_socks;
|
||||||
|
static Common::CriticalSection connection_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CEXIGecko
|
class CEXIGecko
|
||||||
@ -36,9 +57,8 @@ class CEXIGecko
|
|||||||
, private GeckoSockServer
|
, private GeckoSockServer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CEXIGecko();
|
CEXIGecko() {}
|
||||||
void SetCS(int _iCS);
|
bool IsPresent() { return true; }
|
||||||
bool IsPresent();
|
|
||||||
void ImmReadWrite(u32 &_uData, u32 _uSize);
|
void ImmReadWrite(u32 &_uData, u32 _uSize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -53,9 +73,6 @@ private:
|
|||||||
CMD_CHK_RX = 0xd,
|
CMD_CHK_RX = 0xd,
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 m_uPosition;
|
|
||||||
bool recv_fifo;
|
|
||||||
|
|
||||||
static const u32 ident = 0x04700000;
|
static const u32 ident = 0x04700000;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user