Merge branch 'wii_bb'

Adds Balance Board support.
This commit is contained in:
Matthew Parlane 2013-05-21 23:34:58 +12:00
commit 86b4a87fef
17 changed files with 529 additions and 182 deletions

View File

@ -394,10 +394,10 @@ void EmuThread()
Wiimote::Initialize(g_pWindowHandle);
// Activate wiimotes which don't have source set to "None"
for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
for (unsigned int i = 0; i != MAX_BBMOTES; ++i)
if (g_wiimote_sources[i])
GetUsbPointer()->AccessWiiMote(i | 0x100)->
Activate(true);
GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(true);
}
// The hardware is initialized.

View File

@ -42,9 +42,10 @@ void Shutdown()
void Initialize(void* const hwnd)
{
// add 4 wiimotes
for (unsigned int i = 0; i<4; ++i)
for (unsigned int i = WIIMOTE_CHAN_0; i<MAX_BBMOTES; ++i)
g_plugin.controllers.push_back(new WiimoteEmu::Wiimote(i));
g_controller_interface.SetHwnd(hwnd);
g_controller_interface.Initialize();
@ -134,7 +135,7 @@ void Update(int _number)
unsigned int GetAttached()
{
unsigned int attached = 0;
for (unsigned int i=0; i<4; ++i)
for (unsigned int i=0; i<MAX_BBMOTES; ++i)
if (g_wiimote_sources[i])
attached |= (1 << i);
return attached;
@ -151,7 +152,7 @@ void DoState(u8 **ptr, PointerWrap::Mode mode)
// TODO:
PointerWrap p(ptr, mode);
for (unsigned int i=0; i<4; ++i)
for (unsigned int i=0; i<MAX_BBMOTES; ++i)
((WiimoteEmu::Wiimote*)g_plugin.controllers[i])->DoState(p);
}

View File

@ -8,7 +8,16 @@
#include "../../InputCommon/Src/InputConfig.h"
#include "ChunkFile.h"
#define MAX_WIIMOTES 4
enum {
WIIMOTE_CHAN_0 = 0,
WIIMOTE_CHAN_1,
WIIMOTE_CHAN_2,
WIIMOTE_CHAN_3,
WIIMOTE_BALANCE_BOARD,
MAX_WIIMOTES = WIIMOTE_BALANCE_BOARD,
MAX_BBMOTES = 5,
};
#define WIIMOTE_INI_NAME "WiimoteNew"
@ -20,7 +29,7 @@ enum
WIIMOTE_SRC_HYBRID = 3, // emu + real
};
extern unsigned int g_wiimote_sources[MAX_WIIMOTES];
extern unsigned int g_wiimote_sources[MAX_BBMOTES];
namespace Wiimote
{

View File

@ -32,9 +32,10 @@ WiimoteScanner::~WiimoteScanner()
void WiimoteScanner::Update()
{}
std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimote* & found_board)
{
return std::vector<Wiimote*>();
found_wiimotes.clear();
found_board = NULL;
}
bool WiimoteScanner::IsReady() const

View File

@ -63,23 +63,22 @@ WiimoteScanner::~WiimoteScanner()
void WiimoteScanner::Update()
{}
std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimote* & found_board)
{
std::vector<Wiimote*> found_wiimotes;
// supposedly 1.28 seconds
int const wait_len = 1;
int const max_infos = 255;
inquiry_info scan_infos[max_infos] = {};
auto* scan_infos_ptr = scan_infos;
found_board = NULL;
// Scan for bluetooth devices
int const found_devices = hci_inquiry(device_id, wait_len, max_infos, NULL, &scan_infos_ptr, IREQ_CACHE_FLUSH);
if (found_devices < 0)
{
ERROR_LOG(WIIMOTE, "Error searching for bluetooth devices.");
return found_wiimotes;
return;
}
DEBUG_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices);
@ -91,7 +90,7 @@ std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
// BT names are a maximum of 248 bytes apparently
char name[255] = {};
if (hci_read_remote_name(device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 0) < 0)
if (hci_read_remote_name(device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 1000) < 0)
{
ERROR_LOG(WIIMOTE, "name request failed");
continue;
@ -119,14 +118,20 @@ std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
auto* const wm = new Wiimote;
wm->bdaddr = scan_infos[i].bdaddr;
found_wiimotes.push_back(wm);
NOTICE_LOG(WIIMOTE, "Found wiimote (%s).", bdaddr_str);
if(IsBalanceBoardName(name))
{
found_board = wm;
NOTICE_LOG(WIIMOTE, "Found balance board (%s).", bdaddr_str);
}
else
{
found_wiimotes.push_back(wm);
NOTICE_LOG(WIIMOTE, "Found wiimote (%s).", bdaddr_str);
}
}
}
}
return found_wiimotes;
}
// Connect to a wiimote with a known address.

View File

@ -138,6 +138,10 @@ inline void init_lib()
namespace WiimoteReal
{
int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len);
int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index);
template <typename T>
void ProcessWiimotes(bool new_scan, T& callback);
@ -183,7 +187,7 @@ void WiimoteScanner::Update()
// Does not replace already found wiimotes even if they are disconnected.
// wm is an array of max_wiimotes wiimotes
// Returns the total number of found and connected wiimotes.
std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimote* & found_board)
{
ProcessWiimotes(true, [](HANDLE hRadio, const BLUETOOTH_RADIO_INFO& rinfo, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{
@ -198,8 +202,6 @@ std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
// Get all hid devices connected
HDEVINFO const device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
std::vector<Wiimote*> wiimotes;
SP_DEVICE_INTERFACE_DATA device_data;
device_data.cbSize = sizeof(device_data);
PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL;
@ -214,10 +216,24 @@ std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
// Query the data for this device
if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL))
{
{
auto const wm = new Wiimote;
wm->devicepath = detail_data->DevicePath;
wiimotes.push_back(wm);
bool real_wiimote = false, is_bb = false;
CheckDeviceType(wm->devicepath, real_wiimote, is_bb);
if (is_bb)
{
found_board = wm;
}
else if (real_wiimote)
{
found_wiimotes.push_back(wm);
}
else
{
free(wm);
}
}
free(detail_data);
@ -229,7 +245,178 @@ std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
//if (!wiimotes.empty())
// SLEEP(2000);
return wiimotes;
}
int CheckDeviceType_Write(HANDLE &dev_handle, const u8* buf, int size, int attempts)
{
OVERLAPPED hid_overlap_write = OVERLAPPED();
hid_overlap_write.hEvent = CreateEvent(NULL, true, false, NULL);
enum win_bt_stack_t stack = MSBT_STACK_UNKNOWN;
DWORD written = 0;
for (; attempts>0; --attempts)
{
if (_IOWrite(dev_handle, hid_overlap_write, stack, buf, size))
{
auto const wait_result = WaitForSingleObject(hid_overlap_write.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
if (WAIT_TIMEOUT == wait_result)
{
WARN_LOG(WIIMOTE, "CheckDeviceType_Write: A timeout occurred on writing to Wiimote.");
CancelIo(dev_handle);
continue;
}
else if (WAIT_FAILED == wait_result)
{
WARN_LOG(WIIMOTE, "CheckDeviceType_Write: A wait error occurred on writing to Wiimote.");
CancelIo(dev_handle);
continue;
}
if (GetOverlappedResult(dev_handle, &hid_overlap_write, &written, TRUE))
{
break;
}
}
}
CloseHandle(hid_overlap_write.hEvent);
return written;
}
int CheckDeviceType_Read(HANDLE &dev_handle, u8* buf, int attempts)
{
OVERLAPPED hid_overlap_read = OVERLAPPED();
hid_overlap_read.hEvent = CreateEvent(NULL, true, false, NULL);
int read = 0;
for (; attempts>0; --attempts)
{
read = _IORead(dev_handle, hid_overlap_read, buf, 1);
if (read > 0)
break;
}
CloseHandle(hid_overlap_read.hEvent);
return read;
}
// A convoluted way of checking if a device is a Wii Balance Board and if it is a connectable Wiimote.
// Because nothing on Windows should be easy.
// (We can't seem to easily identify the bluetooth device an HID device belongs to...)
void WiimoteScanner::CheckDeviceType(std::basic_string<TCHAR> &devicepath, bool &real_wiimote, bool &is_bb)
{
real_wiimote = false;
is_bb = false;
#ifdef SHARE_WRITE_WIIMOTES
std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
if (g_connected_wiimotes.count(devicepath) != 0)
return;
#endif
HANDLE dev_handle = CreateFile(devicepath.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
NULL);
if (dev_handle == INVALID_HANDLE_VALUE)
return;
// enable to only check for official nintendo wiimotes/bb's
bool check_vidpid = false;
HIDD_ATTRIBUTES attrib;
attrib.Size = sizeof(attrib);
if (!check_vidpid ||
(HidD_GetAttributes(dev_handle, &attrib) &&
(attrib.VendorID == 0x057e) &&
(attrib.ProductID == 0x0306)))
{
int rc = 0;
// max_cycles insures we are never stuck here due to bad coding...
int max_cycles = 20;
u8 buf[MAX_PAYLOAD] = {0};
u8 const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0};
rc = CheckDeviceType_Write(dev_handle,
req_status_report,
sizeof(req_status_report),
1);
while (rc > 0 && --max_cycles > 0)
{
if ((rc = CheckDeviceType_Read(dev_handle, buf, 1)) <= 0)
{
// DEBUG_LOG(WIIMOTE, "CheckDeviceType: Read failed...");
break;
}
switch (buf[1])
{
case WM_STATUS_REPORT:
{
// DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Status Report");
wm_status_report * wsr = (wm_status_report*)&buf[2];
if (wsr->extension)
{
// Wiimote with extension, we ask it what kind.
u8 read_ext[MAX_PAYLOAD] = {0};
read_ext[0] = WM_SET_REPORT | WM_BT_OUTPUT;
read_ext[1] = WM_READ_DATA;
// Extension type register.
*(u32*)&read_ext[2] = Common::swap32(0x4a400fa);
// Size.
*(u16*)&read_ext[6] = Common::swap16(6);
rc = CheckDeviceType_Write(dev_handle, read_ext, 8, 1);
}
else
{
real_wiimote = true;
// Normal Wiimote, exit while and be happy.
rc = -1;
}
break;
}
case WM_ACK_DATA:
{
// DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Ack");
break;
}
case WM_READ_DATA_REPLY:
{
// DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Data Reply");
wm_read_data_reply * wrdr
= (wm_read_data_reply*)&buf[2];
// Check if it has returned what we asked.
if (Common::swap16(wrdr->address) == 0x00fa)
{
real_wiimote = true;
// 0x020420A40000ULL means balance board.
u64 ext_type = (*(u64*)&wrdr->data[0]);
// DEBUG_LOG(WIIMOTE,
// "CheckDeviceType: GOT EXT TYPE %llX",
// ext_type);
is_bb = ext_type == 0x020420A40000ULL;
}
else
{
ERROR_LOG(WIIMOTE,
"CheckDeviceType: GOT UNREQUESTED ADDRESS %X",
Common::swap16(wrdr->address));
}
// force end
rc = -1;
break;
}
default:
{
// We let read try again incase there is another packet waiting.
// DEBUG_LOG(WIIMOTE, "CheckDeviceType: GOT UNKNOWN REPLY: %X", buf[1]);
break;
}
}
}
}
CloseHandle(dev_handle);
}
bool WiimoteScanner::IsReady() const
@ -355,7 +542,7 @@ bool Wiimote::IsConnected() const
// positive = read packet
// negative = didn't read packet
// zero = error
int Wiimote::IORead(u8* buf)
int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index)
{
// Add data report indicator byte (here, 0xa1)
buf[0] = 0xa1;
@ -408,78 +595,92 @@ int Wiimote::IORead(u8* buf)
return bytes + 1;
}
int Wiimote::IOWrite(const u8* buf, int len)
// positive = read packet
// negative = didn't read packet
// zero = error
int Wiimote::IORead(u8* buf)
{
return _IORead(dev_handle, hid_overlap_read, buf, index);
}
int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len)
{
switch (stack)
{
case MSBT_STACK_UNKNOWN:
{
// Try to auto-detect the stack type
stack = MSBT_STACK_BLUESOLEIL;
if (IOWrite(buf, len))
return 1;
stack = MSBT_STACK_MS;
if (IOWrite(buf, len))
return 1;
stack = MSBT_STACK_UNKNOWN;
break;
}
case MSBT_STACK_MS:
{
auto result = HidD_SetOutputReport(dev_handle, const_cast<u8*>(buf) + 1, len - 1);
//FlushFileBuffers(dev_handle);
if (!result)
case MSBT_STACK_UNKNOWN:
{
auto err = GetLastError();
if (err == 121)
// Try to auto-detect the stack type
stack = MSBT_STACK_BLUESOLEIL;
if (_IOWrite(dev_handle, hid_overlap_write, stack, buf, len))
return 1;
stack = MSBT_STACK_MS;
if (_IOWrite(dev_handle, hid_overlap_write, stack, buf, len))
return 1;
stack = MSBT_STACK_UNKNOWN;
break;
}
case MSBT_STACK_MS:
{
auto result = HidD_SetOutputReport(dev_handle, const_cast<u8*>(buf) + 1, len - 1);
//FlushFileBuffers(dev_handle);
if (!result)
{
// Semaphore timeout
NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to the Wiimote");
auto err = GetLastError();
if (err == 121)
{
// Semaphore timeout
NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to the Wiimote");
}
else
{
WARN_LOG(WIIMOTE, "IOWrite[MSBT_STACK_MS]: ERROR: %08x", err);
}
}
return result;
break;
}
case MSBT_STACK_BLUESOLEIL:
{
u8 big_buf[MAX_PAYLOAD];
if (len < MAX_PAYLOAD)
{
std::copy(buf, buf + len, big_buf);
std::fill(big_buf + len, big_buf + MAX_PAYLOAD, 0);
buf = big_buf;
}
ResetEvent(hid_overlap_write.hEvent);
DWORD bytes = 0;
if (WriteFile(dev_handle, buf + 1, MAX_PAYLOAD - 1, &bytes, &hid_overlap_write))
{
// WriteFile always returns true with bluesoleil.
return 1;
}
else
{
WARN_LOG(WIIMOTE, "IOWrite[MSBT_STACK_MS]: ERROR: %08x", err);
auto const err = GetLastError();
if (ERROR_IO_PENDING == err)
{
CancelIo(dev_handle);
}
}
break;
}
return result;
break;
}
case MSBT_STACK_BLUESOLEIL:
{
u8 big_buf[MAX_PAYLOAD];
if (len < MAX_PAYLOAD)
{
std::copy(buf, buf + len, big_buf);
std::fill(big_buf + len, big_buf + MAX_PAYLOAD, 0);
buf = big_buf;
}
ResetEvent(hid_overlap_write.hEvent);
DWORD bytes = 0;
if (WriteFile(dev_handle, buf + 1, MAX_PAYLOAD - 1, &bytes, &hid_overlap_write))
{
// WriteFile always returns true with bluesoleil.
return 1;
}
else
{
auto const err = GetLastError();
if (ERROR_IO_PENDING == err)
{
CancelIo(dev_handle);
}
}
break;
}
}
return 0;
}
int Wiimote::IOWrite(const u8* buf, int len)
{
return _IOWrite(dev_handle, hid_overlap_write, stack, buf, len);
}
// invokes callback for each found wiimote bluetooth device
template <typename T>
void ProcessWiimotes(bool new_scan, T& callback)
@ -498,7 +699,7 @@ void ProcessWiimotes(bool new_scan, T& callback)
BLUETOOTH_FIND_RADIO_PARAMS radioParam;
radioParam.dwSize = sizeof(radioParam);
HANDLE hRadio;
// TODO: save radio(s) in the WiimoteScanner constructor?

View File

@ -116,22 +116,21 @@ WiimoteScanner::~WiimoteScanner()
void WiimoteScanner::Update()
{}
std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimote* & found_board)
{
// TODO: find the device in the constructor and save it for later
std::vector<Wiimote*> wiimotes;
IOBluetoothHostController *bth;
IOBluetoothDeviceInquiry *bti;
SearchBT *sbt;
NSEnumerator *en;
found_board = NULL;
bth = [[IOBluetoothHostController alloc] init];
if ([bth addressAsString] == nil)
{
WARN_LOG(WIIMOTE, "No bluetooth host controller");
[bth release];
return wiimotes;
return;
}
sbt = [[SearchBT alloc] init];
@ -162,14 +161,20 @@ std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
Wiimote *wm = new Wiimote();
wm->btd = dev;
wiimotes.push_back(wm);
if(IsBalanceBoardName([[dev name] UTF8String]))
{
found_board = wm;
}
else
{
found_wiimotes.push_back(wm);
}
}
[bth release];
[bti release];
[sbt release];
return wiimotes;
}
bool WiimoteScanner::IsReady() const

View File

@ -17,12 +17,13 @@
#include "../WiimoteEmu/WiimoteHid.h"
unsigned int g_wiimote_sources[MAX_WIIMOTES];
unsigned int g_wiimote_sources[MAX_BBMOTES];
namespace WiimoteReal
{
void HandleFoundWiimotes(const std::vector<Wiimote*>&);
void TryToConnectBalanceBoard(Wiimote*);
void TryToConnectWiimote(Wiimote*);
void HandleWiimoteDisconnect(int index);
void DoneWithWiimote(int index);
@ -31,8 +32,7 @@ bool g_real_wiimotes_initialized = false;
std::recursive_mutex g_refresh_lock;
Wiimote* g_wiimotes[MAX_WIIMOTES];
Wiimote* g_wiimotes[MAX_BBMOTES];
WiimoteScanner g_wiimote_scanner;
Wiimote::Wiimote()
@ -285,7 +285,7 @@ bool Wiimote::Prepare(int _index)
u8 const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REPORT_MODE, 0, WM_REPORT_CORE};
// Set the active LEDs and turn on rumble.
u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << index | 0x1)};
u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << (index%WIIMOTE_BALANCE_BOARD) | 0x1)};
// Turn off rumble
u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_RUMBLE, 0};
@ -325,11 +325,25 @@ unsigned int CalculateWantedWiimotes()
return wanted_wiimotes;
}
unsigned int CalculateWantedBB()
{
unsigned int wanted_bb = 0;
if (WIIMOTE_SRC_REAL & g_wiimote_sources[WIIMOTE_BALANCE_BOARD] && !g_wiimotes[WIIMOTE_BALANCE_BOARD])
++wanted_bb;
return wanted_bb;
}
void WiimoteScanner::WantWiimotes(bool do_want)
{
m_want_wiimotes = do_want;
}
void WiimoteScanner::WantBB(bool do_want)
{
m_want_bb = do_want;
}
void WiimoteScanner::StartScanning()
{
if (!m_run_thread)
@ -352,7 +366,7 @@ void CheckForDisconnectedWiimotes()
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
if (g_wiimotes[i] && !g_wiimotes[i]->IsConnected())
HandleWiimoteDisconnect(i);
}
@ -366,12 +380,13 @@ void WiimoteScanner::ThreadFunc()
while (m_run_thread)
{
std::vector<Wiimote*> found_wiimotes;
Wiimote* found_board = NULL;
//NOTICE_LOG(WIIMOTE, "In loop");
if (m_want_wiimotes)
if (m_want_wiimotes || m_want_bb)
{
found_wiimotes = FindWiimotes();
FindWiimotes(found_wiimotes, found_board);
}
else
{
@ -384,7 +399,10 @@ void WiimoteScanner::ThreadFunc()
// TODO: this is a fairly lame place for this
CheckForDisconnectedWiimotes();
HandleFoundWiimotes(found_wiimotes);
if(m_want_wiimotes)
HandleFoundWiimotes(found_wiimotes);
if(m_want_bb && found_board)
TryToConnectBalanceBoard(found_board);
//std::this_thread::yield();
Common::SleepCurrentThread(500);
@ -439,6 +457,10 @@ void LoadSettings()
sec.Get("Source", &g_wiimote_sources[i], i ? WIIMOTE_SRC_NONE : WIIMOTE_SRC_EMU);
}
std::string secname("BalanceBoard");
IniFile::Section& sec = *inifile.GetOrCreateSection(secname.c_str());
sec.Get("Source", &g_wiimote_sources[WIIMOTE_BALANCE_BOARD], WIIMOTE_SRC_NONE);
}
// config dialog calls this when some settings change
@ -452,6 +474,7 @@ void Initialize()
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
g_wiimote_scanner.WantBB(0 != CalculateWantedBB());
if (g_real_wiimotes_initialized)
return;
@ -474,20 +497,21 @@ void Shutdown(void)
g_real_wiimotes_initialized = false;
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
HandleWiimoteDisconnect(i);
}
void ChangeWiimoteSource(unsigned int index, int source)
{
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
g_wiimote_sources[index] = source;
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
// kill real connection (or swap to different slot)
DoneWithWiimote(index);
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
g_wiimote_sources[index] = source;
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
g_wiimote_scanner.WantBB(0 != CalculateWantedBB());
// kill real connection (or swap to different slot)
DoneWithWiimote(index);
}
// reconnect to the emulator
@ -500,7 +524,7 @@ void TryToConnectWiimote(Wiimote* wm)
{
std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);
for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
&& !g_wiimotes[i])
@ -525,16 +549,41 @@ void TryToConnectWiimote(Wiimote* wm)
delete wm;
}
void TryToConnectBalanceBoard(Wiimote* wm)
{
std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);
if (WIIMOTE_SRC_REAL & g_wiimote_sources[WIIMOTE_BALANCE_BOARD]
&& !g_wiimotes[WIIMOTE_BALANCE_BOARD])
{
if (wm->Connect() && wm->Prepare(WIIMOTE_BALANCE_BOARD))
{
NOTICE_LOG(WIIMOTE, "Connected to Balance Board %i.", WIIMOTE_BALANCE_BOARD + 1);
std::swap(g_wiimotes[WIIMOTE_BALANCE_BOARD], wm);
g_wiimotes[WIIMOTE_BALANCE_BOARD]->StartThread();
Host_ConnectWiimote(WIIMOTE_BALANCE_BOARD, true);
}
}
g_wiimote_scanner.WantBB(0 != CalculateWantedBB());
lk.unlock();
delete wm;
}
void DoneWithWiimote(int index)
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
if (g_wiimotes[index])
{
g_wiimotes[index]->StopThread();
// First see if we can use this real Wiimote in another slot.
for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
&& !g_wiimotes[i])
@ -560,9 +609,11 @@ void HandleWiimoteDisconnect(int index)
Wiimote* wm = NULL;
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
std::swap(wm, g_wiimotes[index]);
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
std::swap(wm, g_wiimotes[index]);
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
g_wiimote_scanner.WantBB(0 != CalculateWantedBB());
}
if (wm)
@ -583,31 +634,35 @@ void Refresh()
g_wiimote_scanner.StopScanning();
{
std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);
std::vector<Wiimote*> found_wiimotes;
if (0 != CalculateWantedWiimotes())
{
// Don't hang Dolphin when searching
lk.unlock();
found_wiimotes = g_wiimote_scanner.FindWiimotes();
lk.lock();
}
CheckForDisconnectedWiimotes();
// Brief rumble for already connected Wiimotes.
for (int i = 0; i != MAX_WIIMOTES; ++i)
{
if (g_wiimotes[i])
std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);
std::vector<Wiimote*> found_wiimotes;
Wiimote* found_board = NULL;
if (0 != CalculateWantedWiimotes() || 0 != CalculateWantedBB())
{
g_wiimotes[i]->StopThread();
g_wiimotes[i]->Prepare(i);
g_wiimotes[i]->StartThread();
// Don't hang Dolphin when searching
lk.unlock();
g_wiimote_scanner.FindWiimotes(found_wiimotes, found_board);
lk.lock();
}
}
HandleFoundWiimotes(found_wiimotes);
CheckForDisconnectedWiimotes();
// Brief rumble for already connected Wiimotes.
// Don't do this for Balance Board as it doesn't have rumble anyway.
for (int i = 0; i < MAX_WIIMOTES; ++i)
{
if (g_wiimotes[i])
{
g_wiimotes[i]->StopThread();
g_wiimotes[i]->Prepare(i);
g_wiimotes[i]->StartThread();
}
}
HandleFoundWiimotes(found_wiimotes);
if(found_board)
TryToConnectBalanceBoard(found_board);
}
Initialize();
@ -616,7 +671,6 @@ void Refresh()
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size);
}
@ -656,7 +710,14 @@ bool IsValidBluetoothName(const std::string& name)
{
return
"Nintendo RVL-CNT-01" == name ||
"Nintendo RVL-CNT-01-TR" == name;
"Nintendo RVL-CNT-01-TR" == name ||
IsBalanceBoardName(name);
}
bool IsBalanceBoardName(const std::string& name)
{
return
"Nintendo RVL-WBC-01" == name;
}
}; // end of namespace

View File

@ -117,11 +117,12 @@ public:
bool IsReady() const;
void WantWiimotes(bool do_want);
void WantBB(bool do_want);
void StartScanning();
void StopScanning();
std::vector<Wiimote*> FindWiimotes();
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&);
// function called when not looking for more wiimotes
void Update();
@ -133,10 +134,10 @@ private:
volatile bool m_run_thread;
volatile bool m_want_wiimotes;
volatile bool m_want_bb;
#if defined(_WIN32)
void CheckDeviceType(std::basic_string<TCHAR> &devicepath, bool &real_wiimote, bool &is_bb);
#elif defined(__linux__) && HAVE_BLUEZ
int device_id;
int device_sock;
@ -145,7 +146,7 @@ private:
extern std::recursive_mutex g_refresh_lock;
extern WiimoteScanner g_wiimote_scanner;
extern Wiimote *g_wiimotes[4];
extern Wiimote *g_wiimotes[MAX_BBMOTES];
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);
void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);
@ -158,6 +159,7 @@ int FindWiimotes(Wiimote** wm, int max_wiimotes);
void ChangeWiimoteSource(unsigned int index, int source);
bool IsValidBluetoothName(const std::string& name);
bool IsBalanceBoardName(const std::string& name);
}; // WiimoteReal

View File

@ -32,7 +32,7 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De
}
else
{
u8 maxWM = min<u8>(BT_DINF.num_registered, CONF_PAD_MAX_ACTIVE);
u8 maxWM = min<u8>(BT_DINF.num_registered, MAX_BBMOTES);
bdaddr_t tmpBD = BDADDR_ANY;
u8 i = 0;
while (i < maxWM)
@ -43,28 +43,60 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De
tmpBD.b[2] = BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3];
tmpBD.b[1] = BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4];
tmpBD.b[0] = BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5];
if(i == WIIMOTE_BALANCE_BOARD)
{
const char * wmName = "Nintendo RVL-WBC-01";
memcpy(BT_DINF.registered[i].name, wmName, 20);
memcpy(BT_DINF.balance_board.name, wmName, 20);
}
else
{
const char * wmName = "Nintendo RVL-CNT-01";
memcpy(BT_DINF.registered[i].name, wmName, 20);
memcpy(BT_DINF.active[i].name, wmName, 20);
}
INFO_LOG(WII_IPC_WIIMOTE, "Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));
i++;
}
while (i < CONF_PAD_MAX_ACTIVE)
while (i < MAX_BBMOTES)
{
const char * wmName = "Nintendo RVL-CNT-01";
++BT_DINF.num_registered;
BT_DINF.active[i].bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i;
BT_DINF.active[i].bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0;
BT_DINF.active[i].bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79;
BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19;
BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2;
BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11;
memcpy(BT_DINF.registered[i].name, wmName, 20);
if(i == WIIMOTE_BALANCE_BOARD)
{
const char * wmName = "Nintendo RVL-WBC-01";
++BT_DINF.num_registered;
BT_DINF.balance_board.bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i;
BT_DINF.balance_board.bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0;
BT_DINF.balance_board.bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79;
BT_DINF.balance_board.bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19;
BT_DINF.balance_board.bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2;
BT_DINF.balance_board.bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11;
memcpy(BT_DINF.registered[i].name, wmName, 20);
memcpy(BT_DINF.balance_board.name, wmName, 20);
INFO_LOG(WII_IPC_WIIMOTE, "Balance Board %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));
}
else
{
const char * wmName = "Nintendo RVL-CNT-01";
++BT_DINF.num_registered;
BT_DINF.active[i].bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i;
BT_DINF.active[i].bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0;
BT_DINF.active[i].bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79;
BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19;
BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2;
BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11;
memcpy(BT_DINF.registered[i].name, wmName, 20);
INFO_LOG(WII_IPC_WIIMOTE, "Adding to SYSConf Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));
INFO_LOG(WII_IPC_WIIMOTE, "Adding to SYSConf Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));
}
i++;
}
// save now so that when games load sysconf file it includes the new wiimotes
// and the correct order for connected wiimotes
if (!SConfig::GetInstance().m_SYSCONF->SetArrayData("BT.DINF", (u8*)&BT_DINF, sizeof(_conf_pads)) || !SConfig::GetInstance().m_SYSCONF->Save())
@ -99,18 +131,18 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p)
p.DoPOD(m_HCIEndpoint);
p.DoPOD(m_ACLEndpoint);
p.Do(m_last_ticks);
p.DoArray(m_PacketCount,4);
p.DoArray(m_PacketCount,MAX_BBMOTES);
p.Do(m_ScanEnable);
p.Do(m_EventQueue);
m_acl_pool.DoState(p);
for (unsigned int i = 0; i < 4; i++)
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
m_WiiMotes[i].DoState(p);
// Reset the connection of real and hybrid wiimotes
if (p.GetMode() == PointerWrap::MODE_READ && SConfig::GetInstance().m_WiimoteReconnectOnLoad)
{
for (unsigned int i = 0; i < 4; i++)
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
{
if (WIIMOTE_SRC_EMU == g_wiimote_sources[i] || WIIMOTE_SRC_NONE == g_wiimote_sources[i])
continue;

View File

@ -12,6 +12,7 @@
#include "WII_IPC_HLE.h"
#include "WII_IPC_HLE_Device.h"
#include "WII_IPC_HLE_WiiMote.h"
#include "../HW/Wiimote.h"
struct SQueuedEvent
{
@ -193,7 +194,7 @@ private:
}
} m_acl_pool;
u32 m_PacketCount[4];
u32 m_PacketCount[MAX_BBMOTES];
u64 m_last_ticks;
// Send ACL data to a device (wiimote)
@ -274,7 +275,6 @@ private:
#pragma pack(push,1)
#define CONF_PAD_MAX_REGISTERED 10
#define CONF_PAD_MAX_ACTIVE 4
struct _conf_pad_device
{
@ -286,7 +286,7 @@ private:
{
u8 num_registered;
_conf_pad_device registered[CONF_PAD_MAX_REGISTERED];
_conf_pad_device active[CONF_PAD_MAX_ACTIVE];
_conf_pad_device active[MAX_WIIMOTES];
_conf_pad_device balance_board;
u8 unknown[0x45];
};

View File

@ -37,7 +37,7 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305*
, m_HIDInterruptChannel_Config(false)
, m_HIDInterruptChannel_ConfigWait(false)
, m_BD(_BD)
, m_Name("Nintendo RVL-CNT-01")
, m_Name(_Number == WIIMOTE_BALANCE_BOARD ? "Nintendo RVL-WBC-01" : "Nintendo RVL-CNT-01")
, m_pHost(_pHost)
{
DEBUG_LOG(WII_IPC_WIIMOTE, "Wiimote: #%i Constructed", _Number);
@ -277,13 +277,13 @@ void CWII_IPC_HLE_WiiMote::ExecuteL2capCmd(u8* _pData, u32 _Size)
break;
case L2CAP_PSM_HID_CNTL:
if (number < 4)
if (number < MAX_BBMOTES)
Wiimote::ControlChannel(number, pHeader->dcid, pData, DataSize);
break;
case L2CAP_PSM_HID_INTR:
{
if (number < 4)
if (number < MAX_BBMOTES)
{
DEBUG_LOG(WIIMOTE, "Wiimote_InterruptChannel");
DEBUG_LOG(WIIMOTE, " Channel ID: %04x", pHeader->dcid);

View File

@ -392,7 +392,7 @@ void ChangeWiiPads(bool instantly)
if (instantly && (g_numPads >> 4) == controllers)
return;
for (int i = 0; i < 4; i++)
for (int i = 0; i < MAX_BBMOTES; i++)
{
g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE;
GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(IsUsingWiimote(i));

View File

@ -5,6 +5,7 @@
#include "InputConfigDiag.h"
#include "UDPConfigDiag.h"
#include "WxUtils.h"
#include "HW/Wiimote.h"
void GamepadPage::ConfigUDPWii(wxCommandEvent &event)
{
@ -947,7 +948,7 @@ InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin
, m_plugin(plugin)
{
m_pad_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT);
for (unsigned int i = 0; i < plugin.controllers.size(); ++i)
for (unsigned int i = 0; i < std::min(plugin.controllers.size(), (size_t)MAX_WIIMOTES); ++i)
{
GamepadPage* gp = new GamepadPage(m_pad_notebook, m_plugin, i, this);
m_padpages.push_back(gp);

View File

@ -15,7 +15,7 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
wxStaticText* wiimote_label[4];
wxChoice* wiimote_source_ch[4];
for (unsigned int i = 0; i < 4; ++i)
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
wxString str;
str.Printf(_("Wiimote %i"), i + 1);
@ -54,8 +54,25 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
wiimote_sizer->Add(wiimote_configure_bt[i]);
}
wiimote_group->Add(wiimote_sizer, 1, wxEXPAND, 5 );
// "BalanceBoard" layout
wxStaticBoxSizer* const bb_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Balance Board"));
wxFlexGridSizer* const bb_sizer = new wxFlexGridSizer(1, 5, 5);
int source_ctrl_id = wxWindow::NewControlId();
m_wiimote_index_from_ctrl_id.insert(std::pair<wxWindowID, unsigned int>(source_ctrl_id, WIIMOTE_BALANCE_BOARD));
const wxString src_choices[] = { _("None"), _("Real Balance Board") };
wxChoice* bb_source = new wxChoice(this, source_ctrl_id, wxDefaultPosition, wxDefaultSize, sizeof(src_choices)/sizeof(*src_choices), src_choices);
bb_source->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &WiimoteConfigDiag::SelectSource, this);
m_orig_wiimote_sources[WIIMOTE_BALANCE_BOARD] = g_wiimote_sources[WIIMOTE_BALANCE_BOARD];
bb_source->Select(m_orig_wiimote_sources[WIIMOTE_BALANCE_BOARD] ? 1 : 0);
bb_sizer->Add(bb_source, 0, wxALIGN_CENTER_VERTICAL);
bb_group->Add(bb_sizer, 1, wxEXPAND, 5 );
// "Real wiimotes" controls
wxButton* const refresh_btn = new wxButton(this, -1, _("Refresh"), wxDefaultPosition);
refresh_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::RefreshRealWiimotes, this);
@ -166,6 +183,7 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
// Dialog layout
main_sizer->Add(wiimote_group, 0, wxEXPAND | wxALL, 5);
main_sizer->Add(bb_group, 0, wxEXPAND | wxALL, 5);
main_sizer->Add(real_wiimotes_group, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
main_sizer->Add(general_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
@ -196,17 +214,23 @@ void WiimoteConfigDiag::SelectSource(wxCommandEvent& event)
// Revert if the dialog is canceled.
int index = m_wiimote_index_from_ctrl_id[event.GetId()];
WiimoteReal::ChangeWiimoteSource(index, event.GetInt());
if (g_wiimote_sources[index] != WIIMOTE_SRC_EMU && g_wiimote_sources[index] != WIIMOTE_SRC_HYBRID)
wiimote_configure_bt[index]->Disable();
if(index != WIIMOTE_BALANCE_BOARD)
{
WiimoteReal::ChangeWiimoteSource(index, event.GetInt());
if (g_wiimote_sources[index] != WIIMOTE_SRC_EMU && g_wiimote_sources[index] != WIIMOTE_SRC_HYBRID)
wiimote_configure_bt[index]->Disable();
else
wiimote_configure_bt[index]->Enable();
}
else
wiimote_configure_bt[index]->Enable();
{
WiimoteReal::ChangeWiimoteSource(index, event.GetInt() ? WIIMOTE_SRC_REAL : WIIMOTE_SRC_NONE);
}
}
void WiimoteConfigDiag::RevertSource()
{
for (int i = 0; i < 4; ++i)
for (int i = 0; i < MAX_BBMOTES; ++i)
g_wiimote_sources[i] = m_orig_wiimote_sources[i];
}
@ -225,6 +249,10 @@ void WiimoteConfigDiag::Save(wxCommandEvent& event)
sec.Set("Source", (int)g_wiimote_sources[i]);
}
std::string secname("BalanceBoard");
IniFile::Section& sec = *inifile.GetOrCreateSection(secname.c_str());
sec.Set("Source", (int)g_wiimote_sources[WIIMOTE_BALANCE_BOARD]);
inifile.Save(ini_filename);

View File

@ -76,9 +76,9 @@ private:
wxNotebook* m_pad_notebook;
std::map<wxWindowID, unsigned int> m_wiimote_index_from_ctrl_id;
unsigned int m_orig_wiimote_sources[4];
unsigned int m_orig_wiimote_sources[MAX_BBMOTES];
wxButton* wiimote_configure_bt[4];
wxButton* wiimote_configure_bt[MAX_WIIMOTES];
std::map<wxWindowID, unsigned int> m_wiimote_index_from_conf_bt_id;
};

View File

@ -4,6 +4,7 @@
#include "InputConfig.h"
#include "../../Core/Src/ConfigManager.h"
#include "../../Core/Src/HW/Wiimote.h"
InputPlugin::~InputPlugin()
{
@ -18,9 +19,9 @@ bool InputPlugin::LoadConfig(bool isGC)
{
IniFile inifile;
IniFile game_ini;
bool useProfile[4] = {false, false, false, false};
std::string num[4] = {"1", "2", "3", "4"};
std::string profile[4];
bool useProfile[MAX_BBMOTES] = {false, false, false, false, false};
std::string num[MAX_BBMOTES] = {"1", "2", "3", "4", "BB"};
std::string profile[MAX_BBMOTES];
std::string path;
if (SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() != "00000000")