From c37bca75b656a6ecded15f7a6ab55856ff4f382a Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Wed, 7 Jul 2010 02:19:16 +0000 Subject: [PATCH] Make the refresh button on the Wiimote New plugin add new wiimotes in linux, instead of disconnecting and reconnecting those that were already connected. This makes it possible to connect new wiimotes during a game by openning the wiimote configuration dialog and refreshing. You still need to tell dolphin that a new wiimote is connected using Ctrl+F5-F8 or the corresponding menu entries. Also fixed a segmentation fault caused by the UDP Wiimote stuff when a thread was not properly ended. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5847 8ced0084-cf51-0410-be5f-012b33b47a6e --- Externals/WiiUseSrc/Src/io_nix.c | 78 +++++++++++++++++++ Externals/WiiUseSrc/Src/wiiuse.h | 4 + Source/Core/InputCommon/Src/UDPWiimote.cpp | 1 + .../Src/WiimoteReal/WiimoteReal.cpp | 47 +++++++++++ 4 files changed, 130 insertions(+) diff --git a/Externals/WiiUseSrc/Src/io_nix.c b/Externals/WiiUseSrc/Src/io_nix.c index 7bfc996199..129a611fcd 100644 --- a/Externals/WiiUseSrc/Src/io_nix.c +++ b/Externals/WiiUseSrc/Src/io_nix.c @@ -131,6 +131,84 @@ int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { return found_wiimotes; } +// Scan for more wiimotes and add them to the wm structure. +// Does not replace already found wiimotes even if they are disconnected. +// Returns the total number of found wiimotes. +// It would probably be safe to replace wiiuse_find with this function. The only thing +// it does that this does not is reset the bdaddr fields. +int wiiuse_find_more(struct wiimote_t** wm, int max_wiimotes, int timeout) { +int device_id; +int device_sock; +int found_devices; +int found_wiimotes = 0; +int i; + +// Count the number of already found wiimotes +for (i = 0; i < max_wiimotes; ++i) { + if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND)) + found_wiimotes++; +} + +// get the id of the first bluetooth device. +device_id = hci_get_route(NULL); +if (device_id < 0) { + perror("hci_get_route"); + return 0; +} + +// create a socket to the device +device_sock = hci_open_dev(device_id); +if (device_sock < 0) { + perror("hci_open_dev"); + return 0; +} + +inquiry_info scan_info_arr[128]; +inquiry_info* scan_info = scan_info_arr; +memset(&scan_info_arr, 0, sizeof(scan_info_arr)); + +// scan for bluetooth devices for timeout seconds +found_devices = hci_inquiry(device_id, timeout, 128, NULL, &scan_info, IREQ_CACHE_FLUSH); +if (found_devices < 0) { + perror("hci_inquiry"); + return 0; +} + +WIIUSE_INFO("Found %i bluetooth device(s).", found_devices); + +// display discovered devices +for (i = 0; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) { + if ((scan_info[i].dev_class[0] == WM_DEV_CLASS_0) && + (scan_info[i].dev_class[1] == WM_DEV_CLASS_1) && + (scan_info[i].dev_class[2] == WM_DEV_CLASS_2)) + { + int new_wiimote = 1; + int j; + // Determine if this wiimote has already been found. + for (j = 0; j < found_wiimotes && new_wiimote; ++j) + { + if (WIIMOTE_IS_SET(wm[j], WIIMOTE_STATE_DEV_FOUND) && + bacmp(&scan_info[i].bdaddr,&wm[j]->bdaddr) == 0) + new_wiimote = 0; + } + + if (new_wiimote) + { + // found a new device + ba2str(&scan_info[i].bdaddr, wm[found_wiimotes]->bdaddr_str); + + WIIUSE_INFO("Found wiimote (%s) [id %i].", wm[found_wiimotes]->bdaddr_str, wm[found_wiimotes]->unid); + + wm[found_wiimotes]->bdaddr = scan_info[i].bdaddr; + WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND); + ++found_wiimotes; + } + } +} + +close(device_sock); +return found_wiimotes; +} /** * @brief Connect to a wiimote or wiimotes once an address is known. diff --git a/Externals/WiiUseSrc/Src/wiiuse.h b/Externals/WiiUseSrc/Src/wiiuse.h index 4f93da46ed..5883fbf7c6 100644 --- a/Externals/WiiUseSrc/Src/wiiuse.h +++ b/Externals/WiiUseSrc/Src/wiiuse.h @@ -701,6 +701,10 @@ WIIUSE_EXPORT extern int wiiuse_check_system_notification(unsigned int nMsg, WPA WIIUSE_EXPORT extern int wiiuse_register_system_notification(HWND hwnd); #endif +#ifdef __linux__ +int wiiuse_find_more(struct wiimote_t** wm, int max_wiimotes, int timeout); +#endif + /* ir.c */ WIIUSE_EXPORT extern void wiiuse_set_ir(struct wiimote_t* wm, int status); WIIUSE_EXPORT extern void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos); diff --git a/Source/Core/InputCommon/Src/UDPWiimote.cpp b/Source/Core/InputCommon/Src/UDPWiimote.cpp index d48a58fdcb..7a5f586cfa 100644 --- a/Source/Core/InputCommon/Src/UDPWiimote.cpp +++ b/Source/Core/InputCommon/Src/UDPWiimote.cpp @@ -198,6 +198,7 @@ void UDPWiimote::mainThread() UDPWiimote::~UDPWiimote() { d->exit=true; + d->thread->WaitForDeath(); d->termLock.Enter(); d->termLock.Leave(); for (std::list::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++) diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp index a352699812..0c88f4b4f4 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp @@ -102,6 +102,11 @@ Wiimote::Wiimote(wiimote_t* const wm, const unsigned int index) //SendPacket(g_wiimotes_from_wiiuse[i], WM_LEDS, &rpt, sizeof(rpt)); //} + // Rumble briefly + wiiuse_rumble(m_wiimote, 1); + SLEEP(200); + wiiuse_rumble(m_wiimote, 0); + // set LEDs wiiuse_set_leds(m_wiimote, WIIMOTE_LED_1 << m_index); @@ -340,12 +345,54 @@ void Shutdown(void) wiiuse_cleanup(g_wiimotes_from_wiiuse, MAX_WIIMOTES); } +#ifdef __linux__ +void Refresh() +{ + // find the number of slots configured for real wiimotes + unsigned int wanted_wiimotes = 0; + for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) + if (g_wiimote_sources[i] == WIIMOTE_SRC_REAL) + ++wanted_wiimotes; + + // don't scan for wiimotes if we don't want any more + if (wanted_wiimotes <= g_wiimotes_found) + return; + + // scan for wiimotes + unsigned int num_wiimotes = wiiuse_find_more(g_wiimotes_from_wiiuse, wanted_wiimotes, 5); + + DEBUG_LOG(WIIMOTE, "Found %i Real Wiimotes, %i wanted", num_wiimotes, wanted_wiimotes); + + int num_new_wiimotes = wiiuse_connect(g_wiimotes_from_wiiuse, num_wiimotes); + + DEBUG_LOG(WIIMOTE, "Connected to %i additional Real Wiimotes", num_new_wiimotes); + + g_wiimote_critsec.Enter(); // enter + + // create real wiimote class instances, and assign wiimotes for the new wiimotes + for (unsigned int i = g_wiimotes_found, w = g_wiimotes_found; + i < MAX_WIIMOTES && w < num_wiimotes; ++i) + { + if (g_wiimote_sources[i] != WIIMOTE_SRC_REAL || g_wiimotes[i] != NULL) + continue; + + // create/assign wiimote + g_wiimotes[i] = new Wiimote(g_wiimotes_from_wiiuse[w++], i); + } + g_wiimotes_found = num_wiimotes; + + g_wiimote_critsec.Leave(); // leave + + return; +} +#else void Refresh() { // should be fine i think Shutdown(); Initialize(); } +#endif void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) {