Merge pull request #1596 from Tilka/wiimote
WiimoteReal: use inheritance instead of #ifdef
This commit is contained in:
commit
dec2f9f89b
|
@ -9,9 +9,7 @@ namespace WiimoteReal
|
||||||
{
|
{
|
||||||
|
|
||||||
WiimoteScanner::WiimoteScanner()
|
WiimoteScanner::WiimoteScanner()
|
||||||
{
|
{}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WiimoteScanner::~WiimoteScanner()
|
WiimoteScanner::~WiimoteScanner()
|
||||||
{}
|
{}
|
||||||
|
@ -30,43 +28,4 @@ bool WiimoteScanner::IsReady() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::InitInternal()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void Wiimote::TeardownInternal()
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool Wiimote::ConnectInternal()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wiimote::DisconnectInternal()
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Wiimote::IsConnected() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wiimote::IOWakeup()
|
|
||||||
{}
|
|
||||||
|
|
||||||
int Wiimote::IORead(u8* buf)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Wiimote::IOWrite(const u8* buf, size_t len)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wiimote::EnablePowerAssertionInternal()
|
|
||||||
{}
|
|
||||||
void Wiimote::DisablePowerAssertionInternal()
|
|
||||||
{}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,28 @@
|
||||||
namespace WiimoteReal
|
namespace WiimoteReal
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class WiimoteLinux final : public Wiimote
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WiimoteLinux(bdaddr_t bdaddr);
|
||||||
|
~WiimoteLinux() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool ConnectInternal() override;
|
||||||
|
void DisconnectInternal() override;
|
||||||
|
bool IsConnected() const override;
|
||||||
|
void IOWakeup() override;
|
||||||
|
int IORead(u8* buf) override;
|
||||||
|
int IOWrite(u8 const* buf, size_t len) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bdaddr_t m_bdaddr; // Bluetooth address
|
||||||
|
int m_cmd_sock; // Command socket
|
||||||
|
int m_int_sock; // Interrupt socket
|
||||||
|
int m_wakeup_pipe_w;
|
||||||
|
int m_wakeup_pipe_r;
|
||||||
|
};
|
||||||
|
|
||||||
WiimoteScanner::WiimoteScanner()
|
WiimoteScanner::WiimoteScanner()
|
||||||
: m_want_wiimotes()
|
: m_want_wiimotes()
|
||||||
, device_id(-1)
|
, device_id(-1)
|
||||||
|
@ -102,8 +124,7 @@ void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimot
|
||||||
char bdaddr_str[18] = {};
|
char bdaddr_str[18] = {};
|
||||||
ba2str(&scan_infos[i].bdaddr, bdaddr_str);
|
ba2str(&scan_infos[i].bdaddr, bdaddr_str);
|
||||||
|
|
||||||
auto* const wm = new Wiimote;
|
Wiimote* wm = new WiimoteLinux(scan_infos[i].bdaddr);
|
||||||
wm->bdaddr = scan_infos[i].bdaddr;
|
|
||||||
if (IsBalanceBoardName(name))
|
if (IsBalanceBoardName(name))
|
||||||
{
|
{
|
||||||
found_board = wm;
|
found_board = wm;
|
||||||
|
@ -120,10 +141,10 @@ void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimot
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::InitInternal()
|
WiimoteLinux::WiimoteLinux(bdaddr_t bdaddr) : Wiimote(), m_bdaddr(bdaddr)
|
||||||
{
|
{
|
||||||
cmd_sock = -1;
|
m_cmd_sock = -1;
|
||||||
int_sock = -1;
|
m_int_sock = -1;
|
||||||
|
|
||||||
int fds[2];
|
int fds[2];
|
||||||
if (pipe(fds))
|
if (pipe(fds))
|
||||||
|
@ -131,69 +152,69 @@ void Wiimote::InitInternal()
|
||||||
ERROR_LOG(WIIMOTE, "pipe failed");
|
ERROR_LOG(WIIMOTE, "pipe failed");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
wakeup_pipe_w = fds[1];
|
m_wakeup_pipe_w = fds[1];
|
||||||
wakeup_pipe_r = fds[0];
|
m_wakeup_pipe_r = fds[0];
|
||||||
bdaddr = (bdaddr_t){{0, 0, 0, 0, 0, 0}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::TeardownInternal()
|
WiimoteLinux::~WiimoteLinux()
|
||||||
{
|
{
|
||||||
close(wakeup_pipe_w);
|
Shutdown();
|
||||||
close(wakeup_pipe_r);
|
close(m_wakeup_pipe_w);
|
||||||
|
close(m_wakeup_pipe_r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to a wiimote with a known address.
|
// Connect to a wiimote with a known address.
|
||||||
bool Wiimote::ConnectInternal()
|
bool WiimoteLinux::ConnectInternal()
|
||||||
{
|
{
|
||||||
sockaddr_l2 addr;
|
sockaddr_l2 addr;
|
||||||
addr.l2_family = AF_BLUETOOTH;
|
addr.l2_family = AF_BLUETOOTH;
|
||||||
addr.l2_bdaddr = bdaddr;
|
addr.l2_bdaddr = m_bdaddr;
|
||||||
addr.l2_cid = 0;
|
addr.l2_cid = 0;
|
||||||
|
|
||||||
// Output channel
|
// Output channel
|
||||||
addr.l2_psm = htobs(WM_OUTPUT_CHANNEL);
|
addr.l2_psm = htobs(WM_OUTPUT_CHANNEL);
|
||||||
if ((cmd_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 ||
|
if ((m_cmd_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 ||
|
||||||
connect(cmd_sock, (sockaddr*)&addr, sizeof(addr)) < 0)
|
connect(m_cmd_sock, (sockaddr*)&addr, sizeof(addr)) < 0)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WIIMOTE, "Unable to open output socket to wiimote.");
|
DEBUG_LOG(WIIMOTE, "Unable to open output socket to wiimote.");
|
||||||
close(cmd_sock);
|
close(m_cmd_sock);
|
||||||
cmd_sock = -1;
|
m_cmd_sock = -1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Input channel
|
// Input channel
|
||||||
addr.l2_psm = htobs(WM_INPUT_CHANNEL);
|
addr.l2_psm = htobs(WM_INPUT_CHANNEL);
|
||||||
if ((int_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 ||
|
if ((m_int_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 ||
|
||||||
connect(int_sock, (sockaddr*)&addr, sizeof(addr)) < 0)
|
connect(m_int_sock, (sockaddr*)&addr, sizeof(addr)) < 0)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WIIMOTE, "Unable to open input socket from wiimote.");
|
DEBUG_LOG(WIIMOTE, "Unable to open input socket from wiimote.");
|
||||||
close(int_sock);
|
close(m_int_sock);
|
||||||
close(cmd_sock);
|
close(m_cmd_sock);
|
||||||
int_sock = cmd_sock = -1;
|
m_int_sock = m_cmd_sock = -1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::DisconnectInternal()
|
void WiimoteLinux::DisconnectInternal()
|
||||||
{
|
{
|
||||||
close(cmd_sock);
|
close(m_cmd_sock);
|
||||||
close(int_sock);
|
close(m_int_sock);
|
||||||
|
|
||||||
cmd_sock = -1;
|
m_cmd_sock = -1;
|
||||||
int_sock = -1;
|
m_int_sock = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Wiimote::IsConnected() const
|
bool WiimoteLinux::IsConnected() const
|
||||||
{
|
{
|
||||||
return cmd_sock != -1;// && int_sock != -1;
|
return m_cmd_sock != -1;// && int_sock != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::IOWakeup()
|
void WiimoteLinux::IOWakeup()
|
||||||
{
|
{
|
||||||
char c = 0;
|
char c = 0;
|
||||||
if (write(wakeup_pipe_w, &c, 1) != 1)
|
if (write(m_wakeup_pipe_w, &c, 1) != 1)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Unable to write to wakeup pipe.");
|
ERROR_LOG(WIIMOTE, "Unable to write to wakeup pipe.");
|
||||||
}
|
}
|
||||||
|
@ -202,46 +223,46 @@ void Wiimote::IOWakeup()
|
||||||
// positive = read packet
|
// positive = read packet
|
||||||
// negative = didn't read packet
|
// negative = didn't read packet
|
||||||
// zero = error
|
// zero = error
|
||||||
int Wiimote::IORead(u8* buf)
|
int WiimoteLinux::IORead(u8* buf)
|
||||||
{
|
{
|
||||||
// Block select for 1/2000th of a second
|
// Block select for 1/2000th of a second
|
||||||
|
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(int_sock, &fds);
|
FD_SET(m_int_sock, &fds);
|
||||||
FD_SET(wakeup_pipe_r, &fds);
|
FD_SET(m_wakeup_pipe_r, &fds);
|
||||||
|
|
||||||
if (select(int_sock + 1, &fds, nullptr, nullptr, nullptr) == -1)
|
if (select(m_int_sock + 1, &fds, nullptr, nullptr, nullptr) == -1)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Unable to select wiimote %i input socket.", index + 1);
|
ERROR_LOG(WIIMOTE, "Unable to select wiimote %i input socket.", m_index + 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FD_ISSET(wakeup_pipe_r, &fds))
|
if (FD_ISSET(m_wakeup_pipe_r, &fds))
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
if (read(wakeup_pipe_r, &c, 1) != 1)
|
if (read(m_wakeup_pipe_r, &c, 1) != 1)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Unable to read from wakeup pipe.");
|
ERROR_LOG(WIIMOTE, "Unable to read from wakeup pipe.");
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FD_ISSET(int_sock, &fds))
|
if (!FD_ISSET(m_int_sock, &fds))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// Read the pending message into the buffer
|
// Read the pending message into the buffer
|
||||||
int r = read(int_sock, buf, MAX_PAYLOAD);
|
int r = read(m_int_sock, buf, MAX_PAYLOAD);
|
||||||
if (r == -1)
|
if (r == -1)
|
||||||
{
|
{
|
||||||
// Error reading data
|
// Error reading data
|
||||||
ERROR_LOG(WIIMOTE, "Receiving data from wiimote %i.", index + 1);
|
ERROR_LOG(WIIMOTE, "Receiving data from wiimote %i.", m_index + 1);
|
||||||
|
|
||||||
if (errno == ENOTCONN)
|
if (errno == ENOTCONN)
|
||||||
{
|
{
|
||||||
// This can happen if the bluetooth dongle is disconnected
|
// This can happen if the bluetooth dongle is disconnected
|
||||||
ERROR_LOG(WIIMOTE, "Bluetooth appears to be disconnected. "
|
ERROR_LOG(WIIMOTE, "Bluetooth appears to be disconnected. "
|
||||||
"Wiimote %i will be disconnected.", index + 1);
|
"Wiimote %i will be disconnected.", m_index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = 0;
|
r = 0;
|
||||||
|
@ -250,14 +271,9 @@ int Wiimote::IORead(u8* buf)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Wiimote::IOWrite(u8 const* buf, size_t len)
|
int WiimoteLinux::IOWrite(u8 const* buf, size_t len)
|
||||||
{
|
{
|
||||||
return write(int_sock, buf, (int)len);
|
return write(m_int_sock, buf, (int)len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::EnablePowerAssertionInternal()
|
|
||||||
{}
|
|
||||||
void Wiimote::DisablePowerAssertionInternal()
|
|
||||||
{}
|
|
||||||
|
|
||||||
}; // WiimoteReal
|
}; // WiimoteReal
|
||||||
|
|
|
@ -187,10 +187,30 @@ inline void init_lib()
|
||||||
namespace WiimoteReal
|
namespace WiimoteReal
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class WiimoteWindows final : public Wiimote
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WiimoteWindows(const std::basic_string<TCHAR>& path);
|
||||||
|
~WiimoteWindows() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool ConnectInternal() override;
|
||||||
|
void DisconnectInternal() override;
|
||||||
|
bool IsConnected() const override;
|
||||||
|
void IOWakeup() override;
|
||||||
|
int IORead(u8* buf) override;
|
||||||
|
int IOWrite(u8 const* buf, size_t len) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::basic_string<TCHAR> m_devicepath; // Unique wiimote reference
|
||||||
|
HANDLE m_dev_handle; // HID handle
|
||||||
|
OVERLAPPED m_hid_overlap_read; // Overlap handles
|
||||||
|
OVERLAPPED m_hid_overlap_write;
|
||||||
|
enum win_bt_stack_t m_stack; // Type of bluetooth stack to use
|
||||||
|
};
|
||||||
|
|
||||||
int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, size_t len, DWORD* written);
|
int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, size_t len, DWORD* written);
|
||||||
int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index);
|
int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index);
|
||||||
void _IOWakeup(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read);
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ProcessWiimotes(bool new_scan, T& callback);
|
void ProcessWiimotes(bool new_scan, T& callback);
|
||||||
|
@ -272,11 +292,11 @@ void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimot
|
||||||
// Query the data for this device
|
// Query the data for this device
|
||||||
if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, nullptr, nullptr))
|
if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, nullptr, nullptr))
|
||||||
{
|
{
|
||||||
auto const wm = new Wiimote;
|
std::basic_string<TCHAR> device_path(detail_data->DevicePath);
|
||||||
wm->devicepath = detail_data->DevicePath;
|
Wiimote* wm = new WiimoteWindows(device_path);
|
||||||
bool real_wiimote = false, is_bb = false;
|
bool real_wiimote = false, is_bb = false;
|
||||||
|
|
||||||
CheckDeviceType(wm->devicepath, real_wiimote, is_bb);
|
CheckDeviceType(device_path, real_wiimote, is_bb);
|
||||||
if (is_bb)
|
if (is_bb)
|
||||||
{
|
{
|
||||||
found_board = wm;
|
found_board = wm;
|
||||||
|
@ -500,14 +520,14 @@ bool WiimoteScanner::IsReady() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to a wiimote with a known device path.
|
// Connect to a wiimote with a known device path.
|
||||||
bool Wiimote::ConnectInternal()
|
bool WiimoteWindows::ConnectInternal()
|
||||||
{
|
{
|
||||||
if (IsConnected())
|
if (IsConnected())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#ifdef SHARE_WRITE_WIIMOTES
|
#ifdef SHARE_WRITE_WIIMOTES
|
||||||
std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
|
std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
|
||||||
if (g_connected_wiimotes.count(devicepath) != 0)
|
if (g_connected_wiimotes.count(m_devicepath) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto const open_flags = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
auto const open_flags = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||||
|
@ -519,13 +539,13 @@ bool Wiimote::ConnectInternal()
|
||||||
auto const open_flags = FILE_SHARE_READ;
|
auto const open_flags = FILE_SHARE_READ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dev_handle = CreateFile(devicepath.c_str(),
|
m_dev_handle = CreateFile(m_devicepath.c_str(),
|
||||||
GENERIC_READ | GENERIC_WRITE, open_flags,
|
GENERIC_READ | GENERIC_WRITE, open_flags,
|
||||||
nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
|
nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
|
||||||
|
|
||||||
if (dev_handle == INVALID_HANDLE_VALUE)
|
if (m_dev_handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
dev_handle = 0;
|
m_dev_handle = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,52 +584,48 @@ bool Wiimote::ConnectInternal()
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
#ifdef SHARE_WRITE_WIIMOTES
|
#ifdef SHARE_WRITE_WIIMOTES
|
||||||
g_connected_wiimotes.insert(devicepath);
|
g_connected_wiimotes.insert(m_devicepath);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::DisconnectInternal()
|
void WiimoteWindows::DisconnectInternal()
|
||||||
{
|
{
|
||||||
if (!IsConnected())
|
if (!IsConnected())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CloseHandle(dev_handle);
|
CloseHandle(m_dev_handle);
|
||||||
dev_handle = 0;
|
m_dev_handle = 0;
|
||||||
|
|
||||||
#ifdef SHARE_WRITE_WIIMOTES
|
#ifdef SHARE_WRITE_WIIMOTES
|
||||||
std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
|
std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
|
||||||
g_connected_wiimotes.erase(devicepath);
|
g_connected_wiimotes.erase(m_devicepath);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::InitInternal()
|
WiimoteWindows::WiimoteWindows(const std::basic_string<TCHAR>& path) : m_devicepath(path)
|
||||||
{
|
{
|
||||||
dev_handle = 0;
|
m_dev_handle = 0;
|
||||||
stack = MSBT_STACK_UNKNOWN;
|
m_stack = MSBT_STACK_UNKNOWN;
|
||||||
|
|
||||||
hid_overlap_read = OVERLAPPED();
|
m_hid_overlap_read = OVERLAPPED();
|
||||||
hid_overlap_read.hEvent = CreateEvent(nullptr, true, false, nullptr);
|
m_hid_overlap_read.hEvent = CreateEvent(nullptr, true, false, nullptr);
|
||||||
|
|
||||||
hid_overlap_write = OVERLAPPED();
|
m_hid_overlap_write = OVERLAPPED();
|
||||||
hid_overlap_write.hEvent = CreateEvent(nullptr, true, false, nullptr);
|
m_hid_overlap_write.hEvent = CreateEvent(nullptr, true, false, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::TeardownInternal()
|
WiimoteWindows::~WiimoteWindows()
|
||||||
{
|
{
|
||||||
CloseHandle(hid_overlap_read.hEvent);
|
Shutdown();
|
||||||
CloseHandle(hid_overlap_write.hEvent);
|
CloseHandle(m_hid_overlap_read.hEvent);
|
||||||
|
CloseHandle(m_hid_overlap_write.hEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Wiimote::IsConnected() const
|
bool WiimoteWindows::IsConnected() const
|
||||||
{
|
{
|
||||||
return dev_handle != 0;
|
return m_dev_handle != 0;
|
||||||
}
|
|
||||||
|
|
||||||
void _IOWakeup(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read)
|
|
||||||
{
|
|
||||||
SetEvent(hid_overlap_read.hEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// positive = read packet
|
// positive = read packet
|
||||||
|
@ -632,7 +648,7 @@ int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index
|
||||||
{
|
{
|
||||||
auto const wait_result = WaitForSingleObject(hid_overlap_read.hEvent, INFINITE);
|
auto const wait_result = WaitForSingleObject(hid_overlap_read.hEvent, INFINITE);
|
||||||
|
|
||||||
// In case the event was signalled by _IOWakeup before the read completed, cancel it.
|
// In case the event was signalled by IOWakeup before the read completed, cancel it.
|
||||||
CancelIo(dev_handle);
|
CancelIo(dev_handle);
|
||||||
|
|
||||||
if (WAIT_FAILED == wait_result)
|
if (WAIT_FAILED == wait_result)
|
||||||
|
@ -666,18 +682,18 @@ int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index
|
||||||
return bytes + 1;
|
return bytes + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::IOWakeup()
|
void WiimoteWindows::IOWakeup()
|
||||||
{
|
{
|
||||||
_IOWakeup(dev_handle, hid_overlap_read);
|
SetEvent(m_hid_overlap_read.hEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// positive = read packet
|
// positive = read packet
|
||||||
// negative = didn't read packet
|
// negative = didn't read packet
|
||||||
// zero = error
|
// zero = error
|
||||||
int Wiimote::IORead(u8* buf)
|
int WiimoteWindows::IORead(u8* buf)
|
||||||
{
|
{
|
||||||
return _IORead(dev_handle, hid_overlap_read, buf, index);
|
return _IORead(m_dev_handle, m_hid_overlap_read, buf, m_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -778,16 +794,11 @@ int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stac
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Wiimote::IOWrite(const u8* buf, size_t len)
|
int WiimoteWindows::IOWrite(const u8* buf, size_t len)
|
||||||
{
|
{
|
||||||
return _IOWrite(dev_handle, hid_overlap_write, stack, buf, len, nullptr);
|
return _IOWrite(m_dev_handle, m_hid_overlap_write, m_stack, buf, len, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::EnablePowerAssertionInternal()
|
|
||||||
{}
|
|
||||||
void Wiimote::DisablePowerAssertionInternal()
|
|
||||||
{}
|
|
||||||
|
|
||||||
// invokes callback for each found wiimote bluetooth device
|
// invokes callback for each found wiimote bluetooth device
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ProcessWiimotes(bool new_scan, T& callback)
|
void ProcessWiimotes(bool new_scan, T& callback)
|
||||||
|
|
|
@ -10,100 +10,41 @@
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation SearchBT
|
|
||||||
- (void) deviceInquiryComplete: (IOBluetoothDeviceInquiry *) sender
|
|
||||||
error: (IOReturn) error
|
|
||||||
aborted: (BOOL) aborted
|
|
||||||
{
|
|
||||||
done = true;
|
|
||||||
CFRunLoopStop(CFRunLoopGetCurrent());
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) deviceInquiryDeviceFound: (IOBluetoothDeviceInquiry *) sender
|
|
||||||
device: (IOBluetoothDevice *) device
|
|
||||||
{
|
|
||||||
NOTICE_LOG(WIIMOTE, "Discovered bluetooth device at %s: %s",
|
|
||||||
[[device addressString] UTF8String],
|
|
||||||
[[device name] UTF8String]);
|
|
||||||
|
|
||||||
if ([[sender foundDevices] count] == maxDevices)
|
|
||||||
[sender stop];
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface ConnectBT: NSObject {}
|
@interface ConnectBT: NSObject {}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation ConnectBT
|
|
||||||
- (void) l2capChannelData: (IOBluetoothL2CAPChannel *) l2capChannel
|
|
||||||
data: (unsigned char *) data
|
|
||||||
length: (NSUInteger) length
|
|
||||||
{
|
|
||||||
IOBluetoothDevice *device = [l2capChannel device];
|
|
||||||
WiimoteReal::Wiimote *wm = nullptr;
|
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lk(WiimoteReal::g_refresh_lock);
|
|
||||||
|
|
||||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
|
||||||
{
|
|
||||||
if (WiimoteReal::g_wiimotes[i] == nullptr)
|
|
||||||
continue;
|
|
||||||
if ([device isEqual: WiimoteReal::g_wiimotes[i]->btd] == TRUE)
|
|
||||||
wm = WiimoteReal::g_wiimotes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wm == nullptr) {
|
|
||||||
ERROR_LOG(WIIMOTE, "Received packet for unknown wiimote");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length > MAX_PAYLOAD) {
|
|
||||||
WARN_LOG(WIIMOTE, "Dropping packet for wiimote %i, too large",
|
|
||||||
wm->index + 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wm->inputlen != -1) {
|
|
||||||
WARN_LOG(WIIMOTE, "Dropping packet for wiimote %i, queue full",
|
|
||||||
wm->index + 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(wm->input, data, length);
|
|
||||||
wm->inputlen = length;
|
|
||||||
|
|
||||||
CFRunLoopStop(CFRunLoopGetCurrent());
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel
|
|
||||||
{
|
|
||||||
IOBluetoothDevice *device = [l2capChannel device];
|
|
||||||
WiimoteReal::Wiimote *wm = nullptr;
|
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lk(WiimoteReal::g_refresh_lock);
|
|
||||||
|
|
||||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
|
||||||
{
|
|
||||||
if (WiimoteReal::g_wiimotes[i] == nullptr)
|
|
||||||
continue;
|
|
||||||
if ([device isEqual: WiimoteReal::g_wiimotes[i]->btd] == TRUE)
|
|
||||||
wm = WiimoteReal::g_wiimotes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wm == nullptr) {
|
|
||||||
ERROR_LOG(WIIMOTE, "Channel for unknown wiimote was closed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WARN_LOG(WIIMOTE, "Lost channel to wiimote %i", wm->index + 1);
|
|
||||||
|
|
||||||
wm->DisconnectInternal();
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
namespace WiimoteReal
|
namespace WiimoteReal
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class WiimoteDarwin final : public Wiimote
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WiimoteDarwin(IOBluetoothDevice* device);
|
||||||
|
~WiimoteDarwin() override;
|
||||||
|
|
||||||
|
// These are not protected/private because ConnectBT needs them.
|
||||||
|
void DisconnectInternal() override;
|
||||||
|
IOBluetoothDevice* m_btd;
|
||||||
|
unsigned char* m_input;
|
||||||
|
int m_inputlen;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool ConnectInternal() override;
|
||||||
|
bool IsConnected() const override;
|
||||||
|
void IOWakeup() override;
|
||||||
|
int IORead(u8* buf) override;
|
||||||
|
int IOWrite(u8 const* buf, size_t len) override;
|
||||||
|
void EnablePowerAssertionInternal() override;
|
||||||
|
void DisablePowerAssertionInternal() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IOBluetoothL2CAPChannel* m_ichan;
|
||||||
|
IOBluetoothL2CAPChannel* m_cchan;
|
||||||
|
bool m_connected;
|
||||||
|
CFRunLoopRef m_wiimote_thread_run_loop;
|
||||||
|
IOPMAssertionID m_pm_assertion;
|
||||||
|
};
|
||||||
|
|
||||||
WiimoteScanner::WiimoteScanner()
|
WiimoteScanner::WiimoteScanner()
|
||||||
: m_run_thread()
|
: m_run_thread()
|
||||||
, m_want_wiimotes()
|
, m_want_wiimotes()
|
||||||
|
@ -164,8 +105,7 @@ void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimot
|
||||||
if (!IsValidBluetoothName([[dev name] UTF8String]))
|
if (!IsValidBluetoothName([[dev name] UTF8String]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Wiimote *wm = new Wiimote();
|
Wiimote* wm = new WiimoteDarwin([dev retain]);
|
||||||
wm->btd = [dev retain];
|
|
||||||
|
|
||||||
if (IsBalanceBoardName([[dev name] UTF8String]))
|
if (IsBalanceBoardName([[dev name] UTF8String]))
|
||||||
{
|
{
|
||||||
|
@ -188,51 +128,52 @@ bool WiimoteScanner::IsReady() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::InitInternal()
|
WiimoteDarwin::WiimoteDarwin(IOBluetoothDevice* device) : m_btd(device)
|
||||||
{
|
{
|
||||||
inputlen = 0;
|
m_inputlen = 0;
|
||||||
m_connected = false;
|
m_connected = false;
|
||||||
m_wiimote_thread_run_loop = nullptr;
|
m_wiimote_thread_run_loop = nullptr;
|
||||||
btd = nil;
|
|
||||||
m_pm_assertion = kIOPMNullAssertionID;
|
m_pm_assertion = kIOPMNullAssertionID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::TeardownInternal()
|
WiimoteDarwin::~WiimoteDarwin()
|
||||||
{
|
{
|
||||||
|
Shutdown();
|
||||||
if (m_wiimote_thread_run_loop)
|
if (m_wiimote_thread_run_loop)
|
||||||
{
|
{
|
||||||
CFRelease(m_wiimote_thread_run_loop);
|
CFRelease(m_wiimote_thread_run_loop);
|
||||||
m_wiimote_thread_run_loop = nullptr;
|
m_wiimote_thread_run_loop = nullptr;
|
||||||
}
|
}
|
||||||
[btd release];
|
[m_btd release];
|
||||||
btd = nil;
|
m_btd = nil;
|
||||||
|
DisablePowerAssertionInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to a wiimote with a known address.
|
// Connect to a wiimote with a known address.
|
||||||
bool Wiimote::ConnectInternal()
|
bool WiimoteDarwin::ConnectInternal()
|
||||||
{
|
{
|
||||||
if (IsConnected())
|
if (IsConnected())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ConnectBT *cbt = [[ConnectBT alloc] init];
|
ConnectBT *cbt = [[ConnectBT alloc] init];
|
||||||
|
|
||||||
cchan = ichan = nil;
|
m_cchan = m_ichan = nil;
|
||||||
|
|
||||||
IOReturn ret = [btd openConnection];
|
IOReturn ret = [m_btd openConnection];
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Unable to open Bluetooth connection to wiimote %i: %x",
|
ERROR_LOG(WIIMOTE, "Unable to open Bluetooth connection to wiimote %i: %x",
|
||||||
index + 1, ret);
|
m_index + 1, ret);
|
||||||
[cbt release];
|
[cbt release];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = [btd openL2CAPChannelSync: &cchan
|
ret = [m_btd openL2CAPChannelSync: &m_cchan
|
||||||
withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt];
|
withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt];
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Unable to open control channel for wiimote %i: %x",
|
ERROR_LOG(WIIMOTE, "Unable to open control channel for wiimote %i: %x",
|
||||||
index + 1, ret);
|
m_index + 1, ret);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
// Apple docs claim:
|
// Apple docs claim:
|
||||||
|
@ -240,20 +181,20 @@ bool Wiimote::ConnectInternal()
|
||||||
// success; the channel must be released when the caller is done with it."
|
// success; the channel must be released when the caller is done with it."
|
||||||
// But without this, the channels get over-autoreleased, even though the
|
// But without this, the channels get over-autoreleased, even though the
|
||||||
// refcounting behavior here is clearly correct.
|
// refcounting behavior here is clearly correct.
|
||||||
[cchan retain];
|
[m_cchan retain];
|
||||||
|
|
||||||
ret = [btd openL2CAPChannelSync: &ichan
|
ret = [m_btd openL2CAPChannelSync: &m_ichan
|
||||||
withPSM: kBluetoothL2CAPPSMHIDInterrupt delegate: cbt];
|
withPSM: kBluetoothL2CAPPSMHIDInterrupt delegate: cbt];
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
WARN_LOG(WIIMOTE, "Unable to open interrupt channel for wiimote %i: %x",
|
WARN_LOG(WIIMOTE, "Unable to open interrupt channel for wiimote %i: %x",
|
||||||
index + 1, ret);
|
m_index + 1, ret);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
[ichan retain];
|
[m_ichan retain];
|
||||||
|
|
||||||
NOTICE_LOG(WIIMOTE, "Connected to wiimote %i at %s",
|
NOTICE_LOG(WIIMOTE, "Connected to wiimote %i at %s",
|
||||||
index + 1, [[btd addressString] UTF8String]);
|
m_index + 1, [[m_btd addressString] UTF8String]);
|
||||||
|
|
||||||
m_connected = true;
|
m_connected = true;
|
||||||
|
|
||||||
|
@ -270,32 +211,32 @@ bad:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect a wiimote.
|
// Disconnect a wiimote.
|
||||||
void Wiimote::DisconnectInternal()
|
void WiimoteDarwin::DisconnectInternal()
|
||||||
{
|
{
|
||||||
[ichan closeChannel];
|
[m_ichan closeChannel];
|
||||||
[ichan release];
|
[m_ichan release];
|
||||||
ichan = nil;
|
m_ichan = nil;
|
||||||
|
|
||||||
[cchan closeChannel];
|
[m_cchan closeChannel];
|
||||||
[cchan release];
|
[m_cchan release];
|
||||||
cchan = nil;
|
m_cchan = nil;
|
||||||
|
|
||||||
[btd closeConnection];
|
[m_btd closeConnection];
|
||||||
|
|
||||||
if (!IsConnected())
|
if (!IsConnected())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i", index + 1);
|
NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i", m_index + 1);
|
||||||
|
|
||||||
m_connected = false;
|
m_connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Wiimote::IsConnected() const
|
bool WiimoteDarwin::IsConnected() const
|
||||||
{
|
{
|
||||||
return m_connected;
|
return m_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::IOWakeup()
|
void WiimoteDarwin::IOWakeup()
|
||||||
{
|
{
|
||||||
if (m_wiimote_thread_run_loop)
|
if (m_wiimote_thread_run_loop)
|
||||||
{
|
{
|
||||||
|
@ -303,24 +244,24 @@ void Wiimote::IOWakeup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Wiimote::IORead(unsigned char *buf)
|
int WiimoteDarwin::IORead(unsigned char *buf)
|
||||||
{
|
{
|
||||||
input = buf;
|
m_input = buf;
|
||||||
inputlen = -1;
|
m_inputlen = -1;
|
||||||
|
|
||||||
CFRunLoopRun();
|
CFRunLoopRun();
|
||||||
|
|
||||||
return inputlen;
|
return m_inputlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Wiimote::IOWrite(const unsigned char *buf, size_t len)
|
int WiimoteDarwin::IOWrite(const unsigned char *buf, size_t len)
|
||||||
{
|
{
|
||||||
IOReturn ret;
|
IOReturn ret;
|
||||||
|
|
||||||
if (!IsConnected())
|
if (!IsConnected())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = [ichan writeAsync: const_cast<void*>((void *)buf) length: (int)len refcon: nil];
|
ret = [m_ichan writeAsync: const_cast<void*>((void *)buf) length: (int)len refcon: nil];
|
||||||
|
|
||||||
if (ret == kIOReturnSuccess)
|
if (ret == kIOReturnSuccess)
|
||||||
return len;
|
return len;
|
||||||
|
@ -328,7 +269,7 @@ int Wiimote::IOWrite(const unsigned char *buf, size_t len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::EnablePowerAssertionInternal()
|
void WiimoteDarwin::EnablePowerAssertionInternal()
|
||||||
{
|
{
|
||||||
if (m_pm_assertion == kIOPMNullAssertionID)
|
if (m_pm_assertion == kIOPMNullAssertionID)
|
||||||
{
|
{
|
||||||
|
@ -337,7 +278,7 @@ void Wiimote::EnablePowerAssertionInternal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::DisablePowerAssertionInternal()
|
void WiimoteDarwin::DisablePowerAssertionInternal()
|
||||||
{
|
{
|
||||||
if (m_pm_assertion != kIOPMNullAssertionID)
|
if (m_pm_assertion != kIOPMNullAssertionID)
|
||||||
{
|
{
|
||||||
|
@ -346,4 +287,94 @@ void Wiimote::DisablePowerAssertionInternal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
@implementation SearchBT
|
||||||
|
- (void) deviceInquiryComplete: (IOBluetoothDeviceInquiry *) sender
|
||||||
|
error: (IOReturn) error
|
||||||
|
aborted: (BOOL) aborted
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
CFRunLoopStop(CFRunLoopGetCurrent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) deviceInquiryDeviceFound: (IOBluetoothDeviceInquiry *) sender
|
||||||
|
device: (IOBluetoothDevice *) device
|
||||||
|
{
|
||||||
|
NOTICE_LOG(WIIMOTE, "Discovered bluetooth device at %s: %s",
|
||||||
|
[[device addressString] UTF8String],
|
||||||
|
[[device name] UTF8String]);
|
||||||
|
|
||||||
|
if ([[sender foundDevices] count] == maxDevices)
|
||||||
|
[sender stop];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ConnectBT
|
||||||
|
- (void) l2capChannelData: (IOBluetoothL2CAPChannel *) l2capChannel
|
||||||
|
data: (unsigned char *) data
|
||||||
|
length: (NSUInteger) length
|
||||||
|
{
|
||||||
|
IOBluetoothDevice *device = [l2capChannel device];
|
||||||
|
WiimoteReal::WiimoteDarwin *wm = nullptr;
|
||||||
|
|
||||||
|
std::lock_guard<std::recursive_mutex> lk(WiimoteReal::g_refresh_lock);
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||||
|
{
|
||||||
|
if (WiimoteReal::g_wiimotes[i] == nullptr)
|
||||||
|
continue;
|
||||||
|
wm = static_cast<WiimoteReal::WiimoteDarwin*>(WiimoteReal::g_wiimotes[i]);
|
||||||
|
if ([device isEqual: wm->m_btd] != TRUE)
|
||||||
|
wm = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wm == nullptr) {
|
||||||
|
ERROR_LOG(WIIMOTE, "Received packet for unknown wiimote");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length > MAX_PAYLOAD) {
|
||||||
|
WARN_LOG(WIIMOTE, "Dropping packet for wiimote %i, too large",
|
||||||
|
wm->m_index + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wm->m_inputlen != -1) {
|
||||||
|
WARN_LOG(WIIMOTE, "Dropping packet for wiimote %i, queue full",
|
||||||
|
wm->m_index + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(wm->m_input, data, length);
|
||||||
|
wm->m_inputlen = length;
|
||||||
|
|
||||||
|
CFRunLoopStop(CFRunLoopGetCurrent());
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel
|
||||||
|
{
|
||||||
|
IOBluetoothDevice *device = [l2capChannel device];
|
||||||
|
WiimoteReal::WiimoteDarwin *wm = nullptr;
|
||||||
|
|
||||||
|
std::lock_guard<std::recursive_mutex> lk(WiimoteReal::g_refresh_lock);
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||||
|
{
|
||||||
|
if (WiimoteReal::g_wiimotes[i] == nullptr)
|
||||||
|
continue;
|
||||||
|
wm = static_cast<WiimoteReal::WiimoteDarwin*>(WiimoteReal::g_wiimotes[i]);
|
||||||
|
if ([device isEqual: wm->m_btd] != TRUE)
|
||||||
|
wm = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wm == nullptr) {
|
||||||
|
ERROR_LOG(WIIMOTE, "Channel for unknown wiimote was closed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WARN_LOG(WIIMOTE, "Lost channel to wiimote %i", wm->m_index + 1);
|
||||||
|
|
||||||
|
wm->DisconnectInternal();
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
|
@ -37,22 +37,18 @@ Wiimote* g_wiimotes[MAX_BBMOTES];
|
||||||
WiimoteScanner g_wiimote_scanner;
|
WiimoteScanner g_wiimote_scanner;
|
||||||
|
|
||||||
Wiimote::Wiimote()
|
Wiimote::Wiimote()
|
||||||
: index()
|
: m_index()
|
||||||
, m_last_input_report()
|
, m_last_input_report()
|
||||||
, m_channel(0)
|
, m_channel(0)
|
||||||
, m_rumble_state()
|
, m_rumble_state()
|
||||||
, m_need_prepare()
|
, m_need_prepare()
|
||||||
{
|
{}
|
||||||
InitInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
Wiimote::~Wiimote()
|
void Wiimote::Shutdown()
|
||||||
{
|
{
|
||||||
DisablePowerAssertionInternal();
|
|
||||||
StopThread();
|
StopThread();
|
||||||
ClearReadQueue();
|
ClearReadQueue();
|
||||||
m_write_reports.Clear();
|
m_write_reports.Clear();
|
||||||
TeardownInternal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// to be called from CPU thread
|
// to be called from CPU thread
|
||||||
|
@ -62,12 +58,9 @@ void Wiimote::WriteReport(Report rpt)
|
||||||
{
|
{
|
||||||
bool const new_rumble_state = (rpt[2] & 0x1) != 0;
|
bool const new_rumble_state = (rpt[2] & 0x1) != 0;
|
||||||
|
|
||||||
|
// If this is a rumble report and the rumble state didn't change, ignore.
|
||||||
if (WM_RUMBLE == rpt[1] && new_rumble_state == m_rumble_state)
|
if (WM_RUMBLE == rpt[1] && new_rumble_state == m_rumble_state)
|
||||||
{
|
|
||||||
// If this is a rumble report and the rumble state didn't change, ignore
|
|
||||||
//ERROR_LOG(WIIMOTE, "Ignoring rumble report.");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
m_rumble_state = new_rumble_state;
|
m_rumble_state = new_rumble_state;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +133,7 @@ void Wiimote::ControlChannel(const u16 channel, const void* const data, const u3
|
||||||
if (hidp->type == HID_TYPE_SET_REPORT)
|
if (hidp->type == HID_TYPE_SET_REPORT)
|
||||||
{
|
{
|
||||||
u8 handshake_ok = HID_HANDSHAKE_SUCCESS;
|
u8 handshake_ok = HID_HANDSHAKE_SUCCESS;
|
||||||
Core::Callback_WiimoteInterruptChannel(index, channel, &handshake_ok, sizeof(handshake_ok));
|
Core::Callback_WiimoteInterruptChannel(m_index, channel, &handshake_ok, sizeof(handshake_ok));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +152,7 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const _data, const
|
||||||
|
|
||||||
auto const data = static_cast<const u8*>(_data);
|
auto const data = static_cast<const u8*>(_data);
|
||||||
Report rpt(data, data + size);
|
Report rpt(data, data + size);
|
||||||
WiimoteEmu::Wiimote *const wm = (WiimoteEmu::Wiimote*)::Wiimote::GetConfig()->controllers[index];
|
WiimoteEmu::Wiimote *const wm = (WiimoteEmu::Wiimote*)::Wiimote::GetConfig()->controllers[m_index];
|
||||||
|
|
||||||
// Convert output DATA packets to SET_REPORT packets.
|
// Convert output DATA packets to SET_REPORT packets.
|
||||||
// Nintendo Wiimotes work without this translation, but 3rd
|
// Nintendo Wiimotes work without this translation, but 3rd
|
||||||
|
@ -202,7 +195,7 @@ bool Wiimote::Read()
|
||||||
if (result > 0 && m_channel > 0)
|
if (result > 0 && m_channel > 0)
|
||||||
{
|
{
|
||||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.iBBDumpPort > 0 &&
|
if (SConfig::GetInstance().m_LocalCoreStartupParameter.iBBDumpPort > 0 &&
|
||||||
index == WIIMOTE_BALANCE_BOARD)
|
m_index == WIIMOTE_BALANCE_BOARD)
|
||||||
{
|
{
|
||||||
static sf::UdpSocket Socket;
|
static sf::UdpSocket Socket;
|
||||||
Socket.send((char*)rpt.data(),
|
Socket.send((char*)rpt.data(),
|
||||||
|
@ -218,7 +211,7 @@ bool Wiimote::Read()
|
||||||
}
|
}
|
||||||
else if (0 == result)
|
else if (0 == result)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Wiimote::IORead failed. Disconnecting Wiimote %d.", index + 1);
|
ERROR_LOG(WIIMOTE, "Wiimote::IORead failed. Disconnecting Wiimote %d.", m_index + 1);
|
||||||
DisconnectInternal();
|
DisconnectInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +228,7 @@ bool Wiimote::Write()
|
||||||
|
|
||||||
if (!is_speaker_data || m_last_audio_report.GetTimeDifference() > 5)
|
if (!is_speaker_data || m_last_audio_report.GetTimeDifference() > 5)
|
||||||
{
|
{
|
||||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.iBBDumpPort > 0 && index == WIIMOTE_BALANCE_BOARD)
|
if (SConfig::GetInstance().m_LocalCoreStartupParameter.iBBDumpPort > 0 && m_index == WIIMOTE_BALANCE_BOARD)
|
||||||
{
|
{
|
||||||
static sf::UdpSocket Socket;
|
static sf::UdpSocket Socket;
|
||||||
Socket.send((char*)rpt.data(), rpt.size(), sf::IpAddress::LocalHost, SConfig::GetInstance().m_LocalCoreStartupParameter.iBBDumpPort);
|
Socket.send((char*)rpt.data(), rpt.size(), sf::IpAddress::LocalHost, SConfig::GetInstance().m_LocalCoreStartupParameter.iBBDumpPort);
|
||||||
|
@ -290,7 +283,7 @@ void Wiimote::Update()
|
||||||
{
|
{
|
||||||
if (!IsConnected())
|
if (!IsConnected())
|
||||||
{
|
{
|
||||||
HandleWiimoteDisconnect(index);
|
HandleWiimoteDisconnect(m_index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,14 +293,14 @@ void Wiimote::Update()
|
||||||
// Send the report
|
// Send the report
|
||||||
if (!rpt.empty() && m_channel > 0)
|
if (!rpt.empty() && m_channel > 0)
|
||||||
{
|
{
|
||||||
Core::Callback_WiimoteInterruptChannel(index, m_channel,
|
Core::Callback_WiimoteInterruptChannel(m_index, m_channel,
|
||||||
rpt.data(), (u32)rpt.size());
|
rpt.data(), (u32)rpt.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::Prepare(int _index)
|
void Wiimote::Prepare(int _index)
|
||||||
{
|
{
|
||||||
index = _index;
|
m_index = _index;
|
||||||
m_need_prepare = true;
|
m_need_prepare = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +310,7 @@ bool Wiimote::PrepareOnThread()
|
||||||
u8 static const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REPORT_MODE, 0, WM_REPORT_CORE};
|
u8 static const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REPORT_MODE, 0, WM_REPORT_CORE};
|
||||||
|
|
||||||
// Set the active LEDs and turn on rumble.
|
// Set the active LEDs and turn on rumble.
|
||||||
u8 static const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << (index%WIIMOTE_BALANCE_BOARD) | 0x1)};
|
u8 static const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << (m_index%WIIMOTE_BALANCE_BOARD) | 0x1)};
|
||||||
|
|
||||||
// Turn off rumble
|
// Turn off rumble
|
||||||
u8 static const rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_RUMBLE, 0};
|
u8 static const rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_RUMBLE, 0};
|
||||||
|
@ -351,7 +344,7 @@ void Wiimote::EmuStop()
|
||||||
|
|
||||||
void Wiimote::EmuResume()
|
void Wiimote::EmuResume()
|
||||||
{
|
{
|
||||||
WiimoteEmu::Wiimote *const wm = (WiimoteEmu::Wiimote*)::Wiimote::GetConfig()->controllers[index];
|
WiimoteEmu::Wiimote *const wm = (WiimoteEmu::Wiimote*)::Wiimote::GetConfig()->controllers[m_index];
|
||||||
|
|
||||||
m_last_input_report.clear();
|
m_last_input_report.clear();
|
||||||
|
|
||||||
|
@ -508,8 +501,6 @@ void Wiimote::StopThread()
|
||||||
IOWakeup();
|
IOWakeup();
|
||||||
if (m_wiimote_thread.joinable())
|
if (m_wiimote_thread.joinable())
|
||||||
m_wiimote_thread.join();
|
m_wiimote_thread.join();
|
||||||
#if defined(__APPLE__)
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::SetReady()
|
void Wiimote::SetReady()
|
||||||
|
@ -554,7 +545,7 @@ void Wiimote::ThreadFunc()
|
||||||
m_need_prepare = false;
|
m_need_prepare = false;
|
||||||
if (!PrepareOnThread())
|
if (!PrepareOnThread())
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Wiimote::PrepareOnThread failed. Disconnecting Wiimote %d.", index + 1);
|
ERROR_LOG(WIIMOTE, "Wiimote::PrepareOnThread failed. Disconnecting Wiimote %d.", m_index + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,9 @@ class Wiimote : NonCopyable
|
||||||
{
|
{
|
||||||
friend class WiimoteEmu::Wiimote;
|
friend class WiimoteEmu::Wiimote;
|
||||||
public:
|
public:
|
||||||
Wiimote();
|
virtual ~Wiimote() {}
|
||||||
~Wiimote();
|
// This needs to be called in derived destructors!
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
void ControlChannel(const u16 channel, const void* const data, const u32 size);
|
void ControlChannel(const u16 channel, const void* const data, const u32 size);
|
||||||
void InterruptChannel(const u16 channel, const void* const data, const u32 size);
|
void InterruptChannel(const u16 channel, const void* const data, const u32 size);
|
||||||
|
@ -47,22 +48,19 @@ public:
|
||||||
void EmuResume();
|
void EmuResume();
|
||||||
void EmuPause();
|
void EmuPause();
|
||||||
|
|
||||||
void EnablePowerAssertionInternal();
|
virtual void EnablePowerAssertionInternal() {}
|
||||||
void DisablePowerAssertionInternal();
|
virtual void DisablePowerAssertionInternal() {}
|
||||||
|
|
||||||
// connecting and disconnecting from physical devices
|
// connecting and disconnecting from physical devices
|
||||||
// (using address inserted by FindWiimotes)
|
// (using address inserted by FindWiimotes)
|
||||||
// these are called from the wiimote's thread.
|
// these are called from the wiimote's thread.
|
||||||
bool ConnectInternal();
|
virtual bool ConnectInternal() = 0;
|
||||||
void DisconnectInternal();
|
virtual void DisconnectInternal() = 0;
|
||||||
|
|
||||||
void InitInternal();
|
|
||||||
void TeardownInternal();
|
|
||||||
|
|
||||||
bool Connect();
|
bool Connect();
|
||||||
|
|
||||||
// TODO: change to something like IsRelevant
|
// TODO: change to something like IsRelevant
|
||||||
bool IsConnected() const;
|
virtual bool IsConnected() const = 0;
|
||||||
|
|
||||||
void Prepare(int index);
|
void Prepare(int index);
|
||||||
bool PrepareOnThread();
|
bool PrepareOnThread();
|
||||||
|
@ -73,32 +71,10 @@ public:
|
||||||
|
|
||||||
void QueueReport(u8 rpt_id, const void* data, unsigned int size);
|
void QueueReport(u8 rpt_id, const void* data, unsigned int size);
|
||||||
|
|
||||||
int index;
|
int m_index;
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
IOBluetoothDevice *btd;
|
|
||||||
IOBluetoothL2CAPChannel *ichan;
|
|
||||||
IOBluetoothL2CAPChannel *cchan;
|
|
||||||
unsigned char* input;
|
|
||||||
int inputlen;
|
|
||||||
bool m_connected;
|
|
||||||
CFRunLoopRef m_wiimote_thread_run_loop;
|
|
||||||
IOPMAssertionID m_pm_assertion;
|
|
||||||
#elif defined(__linux__) && HAVE_BLUEZ
|
|
||||||
bdaddr_t bdaddr; // Bluetooth address
|
|
||||||
int cmd_sock; // Command socket
|
|
||||||
int int_sock; // Interrupt socket
|
|
||||||
int wakeup_pipe_w, wakeup_pipe_r;
|
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
std::basic_string<TCHAR> devicepath; // Unique wiimote reference
|
|
||||||
//ULONGLONG btaddr; // Bluetooth address
|
|
||||||
HANDLE dev_handle; // HID handle
|
|
||||||
OVERLAPPED hid_overlap_read, hid_overlap_write; // Overlap handle
|
|
||||||
enum win_bt_stack_t stack; // Type of bluetooth stack to use
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Wiimote();
|
||||||
Report m_last_input_report;
|
Report m_last_input_report;
|
||||||
u16 m_channel;
|
u16 m_channel;
|
||||||
|
|
||||||
|
@ -106,9 +82,9 @@ private:
|
||||||
void ClearReadQueue();
|
void ClearReadQueue();
|
||||||
void WriteReport(Report rpt);
|
void WriteReport(Report rpt);
|
||||||
|
|
||||||
int IORead(u8* buf);
|
virtual int IORead(u8* buf) = 0;
|
||||||
int IOWrite(u8 const* buf, size_t len);
|
virtual int IOWrite(u8 const* buf, size_t len) = 0;
|
||||||
void IOWakeup();
|
virtual void IOWakeup() = 0;
|
||||||
|
|
||||||
void ThreadFunc();
|
void ThreadFunc();
|
||||||
void SetReady();
|
void SetReady();
|
||||||
|
|
Loading…
Reference in New Issue