UDPWii: Broadcasting it's presence on IPv4 to 255.255.255.255 once every 1.5 seconds. 3-arg Set()-s only worked on strings and doubles :P . Added int and bool variants.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5916 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
dapetcu21 2010-07-19 10:36:30 +00:00
parent a2b1f829cb
commit 9074df896a
5 changed files with 155 additions and 35 deletions

View File

@ -119,6 +119,22 @@ void IniFile::Section::Set(const char* key, const float newValue, const float de
Delete(key); Delete(key);
} }
void IniFile::Section::Set(const char* key, int newValue, int defaultValue)
{
if (newValue != defaultValue)
Set(key, newValue);
else
Delete(key);
}
void IniFile::Section::Set(const char* key, bool newValue, bool defaultValue)
{
if (newValue != defaultValue)
Set(key, newValue);
else
Delete(key);
}
void IniFile::Section::Set(const char* key, const std::vector<std::string>& newValues) void IniFile::Section::Set(const char* key, const std::vector<std::string>& newValues)
{ {
std::string temp; std::string temp;

View File

@ -56,9 +56,13 @@ public:
void Set(const char* key, double newValue) { void Set(const char* key, double newValue) {
Set(key, StringFromFormat("%f", newValue).c_str()); Set(key, StringFromFormat("%f", newValue).c_str());
} }
void Set(const char* key, int newValue, int defaultValue);
void Set(const char* key, int newValue) { void Set(const char* key, int newValue) {
Set(key, StringFromInt(newValue).c_str()); Set(key, StringFromInt(newValue).c_str());
} }
void Set(const char* key, bool newValue, bool defaultValue);
void Set(const char* key, bool newValue) { void Set(const char* key, bool newValue) {
Set(key, StringFromBool(newValue).c_str()); Set(key, StringFromBool(newValue).c_str());
} }

View File

@ -18,7 +18,6 @@
#else #else
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <sys/types.h> #include <sys/types.h>
@ -38,7 +37,9 @@
#endif #endif
#include "Thread.h" #include "Thread.h"
#include "Timer.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <list> #include <list>
@ -46,8 +47,9 @@ struct UDPWiimote::_d
{ {
Common::Thread * thread; Common::Thread * thread;
std::list<sock_t> sockfds; std::list<sock_t> sockfds;
Common::CriticalSection termLock,mutex; Common::CriticalSection termLock,mutex,nameMutex;
volatile bool exit; volatile bool exit;
sock_t bipv4_fd,bipv6_fd;
}; };
int UDPWiimote::noinst=0; int UDPWiimote::noinst=0;
@ -55,7 +57,6 @@ int UDPWiimote::noinst=0;
void _UDPWiiThread(void* arg) void _UDPWiiThread(void* arg)
{ {
((UDPWiimote*)arg)->mainThread(); ((UDPWiimote*)arg)->mainThread();
//NOTICE_LOG(WIIMOTE,"UDPWii thread stopped");
} }
THREAD_RETURN UDPWiiThread(void* arg) THREAD_RETURN UDPWiiThread(void* arg)
@ -64,11 +65,20 @@ THREAD_RETURN UDPWiiThread(void* arg)
return 0; return 0;
} }
UDPWiimote::UDPWiimote(const char *_port) : UDPWiimote::UDPWiimote(const char *_port, const char * name, int _index) :
port(_port), port(_port), displayName(name),
d(new _d) ,x(0),y(0),z(0),naX(0),naY(0),naZ(0),nunX(0),nunY(0), d(new _d) ,x(0),y(0),z(0),naX(0),naY(0),naZ(0),nunX(0),nunY(0),
pointerX(-0.1),pointerY(-0.1),nunMask(0),mask(0),time(0) pointerX(-0.1),pointerY(-0.1),nunMask(0),mask(0),index(_index), int_port(atoi(_port))
{ {
static bool sranded=false;
if (!sranded)
{
srand(time(0));
sranded=true;
}
bcastMagic=rand() & 0xFFFF;
#ifdef _WIN32 #ifdef _WIN32
u_long iMode = 1; u_long iMode = 1;
#endif #endif
@ -87,13 +97,18 @@ UDPWiimote::UDPWiimote(const char *_port) :
#endif #endif
noinst++; noinst++;
//PanicAlert("UDPWii instantiated");
memset(&hints, 0, sizeof hints); memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP hints.ai_flags = AI_PASSIVE; // use my IP
if (!int_port){
cleanup;
err=-1;
return;
}
if ((rv = getaddrinfo(NULL, _port, &hints, &servinfo)) != 0) { if ((rv = getaddrinfo(NULL, _port, &hints, &servinfo)) != 0) {
cleanup; cleanup;
err=-1; err=-1;
@ -106,14 +121,10 @@ UDPWiimote::UDPWiimote(const char *_port) :
if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == BAD_SOCK) { if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == BAD_SOCK) {
continue; continue;
} }
if (bind(sock, p->ai_addr, p->ai_addrlen) == -1) { if (bind(sock, p->ai_addr, p->ai_addrlen) == -1) {
close(sock); close(sock);
continue; continue;
} }
//NOTICE_LOG(WIIMOTE,"UDPWii new listening sock");
d->sockfds.push_back(sock); d->sockfds.push_back(sock);
} }
@ -126,7 +137,8 @@ UDPWiimote::UDPWiimote(const char *_port) :
freeaddrinfo(servinfo); freeaddrinfo(servinfo);
err=0; err=0;
d->exit=false; d->exit=false;
// NOTICE_LOG(WIIMOTE,"UDPWii thread starting"); initBroadcastIPv4();
initBroadcastIPv6();
d->termLock.Enter(); d->termLock.Enter();
d->thread = new Common::Thread(UDPWiiThread,this); d->thread = new Common::Thread(UDPWiiThread,this);
d->termLock.Leave(); d->termLock.Leave();
@ -136,12 +148,12 @@ UDPWiimote::UDPWiimote(const char *_port) :
void UDPWiimote::mainThread() void UDPWiimote::mainThread()
{ {
d->termLock.Enter(); d->termLock.Enter();
// NOTICE_LOG(WIIMOTE,"UDPWii thread started"); Common::Timer time;
fd_set fds; fd_set fds;
struct timeval timeout; struct timeval timeout;
timeout.tv_sec=1; timeout.tv_sec=0;
timeout.tv_usec=500000; timeout.tv_usec=0;
//Common::Thread * thisthr= d->thread; time.Update();
do do
{ {
int maxfd=0; int maxfd=0;
@ -154,12 +166,28 @@ void UDPWiimote::mainThread()
maxfd=(*i)+1; maxfd=(*i)+1;
#endif #endif
} }
d->termLock.Leave();
u64 tleft=timeout.tv_sec*1000+timeout.tv_usec/1000;
u64 telapsed=time.GetTimeDifference();
time.Update();
if (tleft<=telapsed)
{
timeout.tv_sec=1;
timeout.tv_usec=500000;
broadcastPresence();
} else {
tleft-=telapsed;
timeout.tv_sec=tleft/1000;
timeout.tv_usec=(tleft%1000)*1000;
}
d->termLock.Leave(); //VERY hacky. don't like it
if (d->exit) return; if (d->exit) return;
int rt=select(maxfd,&fds,NULL,NULL,&timeout); int rt=select(maxfd,&fds,NULL,NULL,&timeout);
if (d->exit) return; if (d->exit) return;
d->termLock.Enter(); d->termLock.Enter();
if (d->exit) return; if (d->exit) return;
if (rt) if (rt)
{ {
for (std::list<sock_t>::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++) for (std::list<sock_t>::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++)
@ -171,7 +199,9 @@ void UDPWiimote::mainThread()
size_t addr_len; size_t addr_len;
struct sockaddr_storage their_addr; struct sockaddr_storage their_addr;
addr_len = sizeof their_addr; addr_len = sizeof their_addr;
if ((size = recvfrom(fd, (dataz)bf, size , 0,(struct sockaddr *)&their_addr, (socklen_t*)&addr_len)) == -1) if ((size = recvfrom(fd,
(dataz)bf,
size , 0,(struct sockaddr *)&their_addr, (socklen_t*)&addr_len)) == -1)
{ {
ERROR_LOG(WIIMOTE,"UDPWii Packet error"); ERROR_LOG(WIIMOTE,"UDPWii Packet error");
} }
@ -187,12 +217,9 @@ void UDPWiimote::mainThread()
d->mutex.Leave(); d->mutex.Leave();
} }
} }
} else {
broadcastPresence();
} }
} while (!(d->exit)); } while (!(d->exit));
d->termLock.Leave(); d->termLock.Leave();
//delete thisthr;
} }
UDPWiimote::~UDPWiimote() UDPWiimote::~UDPWiimote()
@ -203,9 +230,10 @@ UDPWiimote::~UDPWiimote()
d->termLock.Leave(); d->termLock.Leave();
for (std::list<sock_t>::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++) for (std::list<sock_t>::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++)
close(*i); close(*i);
close(d->bipv4_fd);
close(d->bipv6_fd);
cleanup; cleanup;
delete d; delete d;
//PanicAlert("UDPWii destructed");
} }
#define ACCEL_FLAG (1<<0) #define ACCEL_FLAG (1<<0)
@ -219,11 +247,11 @@ int UDPWiimote::pharsePacket(u8 * bf, size_t size)
if (size<3) return -1; if (size<3) return -1;
if (bf[0]!=0xde) if (bf[0]!=0xde)
return -1; return -1;
if (bf[1]==0) //if (bf[1]==0)
time=0; // time=0;
if (bf[1]<time) //if (bf[1]<time) //NOT LONGER NEEDED TO ALLOW MULTIPLE IPHONES ON A SINGLE PORT
return -1; // return -1;
time=bf[1]; //time=bf[1];
u32 *p=(u32*)(&bf[3]); u32 *p=(u32*)(&bf[3]);
if (bf[2]&ACCEL_FLAG) if (bf[2]&ACCEL_FLAG)
{ {
@ -269,9 +297,67 @@ int UDPWiimote::pharsePacket(u8 * bf, size_t size)
} }
void UDPWiimote::initBroadcastIPv4()
{
d->bipv4_fd=socket(AF_INET, SOCK_DGRAM, 0);
if (d->bipv4_fd == BAD_SOCK)
{
WARN_LOG(WIIMOTE,"socket() failed");
return;
}
int broad=1;
if (setsockopt(d->bipv4_fd,SOL_SOCKET,SO_BROADCAST, &broad, sizeof broad) == -1)
{
WARN_LOG(WIIMOTE,"setsockopt(SO_BROADCAST) failed");
return;
}
}
void UDPWiimote::broadcastIPv4(const void * data, size_t size)
{
struct sockaddr_in their_addr;
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(4431);
their_addr.sin_addr.s_addr = INADDR_BROADCAST;
memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);
int num;
if ((num=sendto(d->bipv4_fd,(const dataz)data,size,0,(struct sockaddr *) &their_addr, sizeof their_addr)) == -1)
{
WARN_LOG(WIIMOTE,"sendto() failed");
return;
}
}
void UDPWiimote::initBroadcastIPv6()
{
//TODO: IPv6 support
}
void UDPWiimote::broadcastIPv6(const void * data, size_t size)
{
//TODO: IPv6 support
}
void UDPWiimote::broadcastPresence() void UDPWiimote::broadcastPresence()
{ {
// NOTICE_LOG(WIIMOTE,"UDPWii broadcasting presence"); size_t slen;
u8 bf[512];
bf[0]=0xdf; //magic number
*((u16*)(&(bf[1])))=htons(bcastMagic); //unique per-wiimote 16-bit ID
bf[3]=(u8)index; //wiimote index
*((u16*)(&(bf[4])))=htons(int_port); //port
d->nameMutex.Enter();
slen=displayName.size();
if (slen>=256)
slen=255;
bf[6]=(u8)slen; //display name size (max 255)
memcpy(&(bf[7]),displayName.c_str(),slen); //display name
d->nameMutex.Leave();
broadcastIPv4(bf,7+slen);
broadcastIPv6(bf,7+slen);
} }
void UDPWiimote::getAccel(float &_x, float &_y, float &_z) void UDPWiimote::getAccel(float &_x, float &_y, float &_z)
@ -281,7 +367,6 @@ void UDPWiimote::getAccel(float &_x, float &_y, float &_z)
_y=(float)y; _y=(float)y;
_z=(float)z; _z=(float)z;
d->mutex.Leave(); d->mutex.Leave();
//NOTICE_LOG(WIIMOTE,"%lf %lf %lf",_x, _y, _z);
} }
u32 UDPWiimote::getButtons() u32 UDPWiimote::getButtons()
@ -324,3 +409,11 @@ const char * UDPWiimote::getPort()
{ {
return port.c_str(); return port.c_str();
} }
void UDPWiimote::changeName(const char * name)
{
d->nameMutex.Enter();
displayName=name;
d->nameMutex.Leave();
}

View File

@ -22,7 +22,7 @@
class UDPWiimote class UDPWiimote
{ {
public: public:
UDPWiimote(const char * port); UDPWiimote(const char * port, const char * name, int index);
virtual ~UDPWiimote(); virtual ~UDPWiimote();
void getAccel(float &x, float &y, float &z); void getAccel(float &x, float &y, float &z);
u32 getButtons(); u32 getButtons();
@ -31,8 +31,9 @@ public:
void getNunchuckAccel(float &x, float &y, float &z); void getNunchuckAccel(float &x, float &y, float &z);
int getErrNo() {return err;}; int getErrNo() {return err;};
const char * getPort(); const char * getPort();
void changeName(const char * name);
private: private:
std::string port; std::string port,displayName;
int pharsePacket(u8 * data, size_t size); int pharsePacket(u8 * data, size_t size);
void mainThread(); void mainThread();
struct _d; //using pimpl because Winsock2.h doesen't have include guards -_- struct _d; //using pimpl because Winsock2.h doesen't have include guards -_-
@ -43,10 +44,16 @@ private:
double pointerX,pointerY; double pointerX,pointerY;
u8 nunMask; u8 nunMask;
u32 mask; u32 mask;
u16 bcastMagic;
int err; int err;
int index;
int int_port;
static int noinst; static int noinst;
friend void _UDPWiiThread(void* arg); friend void _UDPWiiThread(void* arg);
void broadcastPresence(); void broadcastPresence();
u8 time; void broadcastIPv4(const void * data, size_t size);
void broadcastIPv6(const void * data, size_t size);
void initBroadcastIPv4();
void initBroadcastIPv6();
}; };
#endif #endif

View File

@ -69,7 +69,7 @@ void UDPWrapper::Refresh()
if (strcmp(inst->getPort(),port.c_str())) if (strcmp(inst->getPort(),port.c_str()))
{ {
delete inst; delete inst;
inst= new UDPWiimote(port.c_str()); inst= new UDPWiimote(port.c_str(),"Dolphin-Emu",index); //TODO: Changeable display name
} }
return; return;
} }
@ -81,7 +81,7 @@ void UDPWrapper::Refresh()
return; return;
} }
//else //else
inst= new UDPWiimote(port.c_str()); inst= new UDPWiimote(port.c_str(),"Dolphin-Emu",index);
} }
UDPWrapper::~UDPWrapper() UDPWrapper::~UDPWrapper()