Skip to content

Commit 9d3c435

Browse files
committed
Add preliminary SBB support.
1 parent e193691 commit 9d3c435

10 files changed

+246
-137
lines changed

SerialPrograms/Source/Controllers/ControllerDescriptor.cpp

Lines changed: 3 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,16 @@
44
*
55
*/
66

7-
#include <iterator>
87
#include "Common/Cpp/Exceptions.h"
98
#include "Common/Cpp/Json/JsonValue.h"
109
#include "Common/Cpp/Json/JsonObject.h"
1110
#include "ControllerCapability.h"
1211
#include "ControllerDescriptor.h"
1312
#include "NullController.h"
1413

15-
// REMOVE
16-
#include <iostream>
17-
using std::cout;
18-
using std::endl;
14+
//#include <iostream>
15+
//using std::cout;
16+
//using std::endl;
1917

2018
namespace PokemonAutomation{
2119

@@ -41,44 +39,6 @@ void InterfaceType::register_factory(
4139

4240

4341

44-
#if 0
45-
std::vector<std::shared_ptr<const ControllerDescriptor>>
46-
get_compatible_descriptors(const ControllerRequirements& requirements){
47-
std::vector<std::shared_ptr<const ControllerDescriptor>> ret;
48-
49-
// Null controller goes first.
50-
ret.emplace_back(new NullControllerDescriptor());
51-
52-
// Add all other controllers. We don't filter them at this time.
53-
for (const auto& controller_interface : ALL_CONTROLLER_INTERFACES){
54-
if (controller_interface.first == ControllerInterface::None){
55-
continue;
56-
}
57-
std::vector<std::shared_ptr<const ControllerDescriptor>> list = controller_interface.second->list();
58-
std::move(list.begin(), list.end(), std::back_inserter(ret));
59-
}
60-
61-
#if 0
62-
// Find all the devices in common between the supported list and the
63-
// required list. For each of those, enumerate all the descriptors and
64-
// combine them into a single list.
65-
for (const auto& device : requirements.map()){
66-
auto iter = ALL_CONTROLLER_INTERFACES.find(device.first);
67-
if (iter != ALL_CONTROLLER_INTERFACES.end()){
68-
std::vector<std::shared_ptr<const ControllerDescriptor>> list = iter->second->list();
69-
std::move(list.begin(), list.end(), std::back_inserter(ret));
70-
}
71-
}
72-
#endif
73-
74-
return ret;
75-
}
76-
#endif
77-
78-
79-
80-
81-
8242

8343
ControllerOption::ControllerOption()
8444
: m_controller_type(ControllerType::None)
@@ -130,11 +90,6 @@ void ControllerOption::load_json(const JsonValue& json){
13090
m_descriptor_cache[item.first] = item.second->make(*params);
13191
}
13292

133-
// const JsonValue* params = obj->get_value("Parameters");
134-
// if (params == nullptr){
135-
// break;
136-
// }
137-
13893
auto iter = m_descriptor_cache.find(CONTROLLER_INTERFACE_STRINGS.get_enum(*type, ControllerInterface::None));
13994
if (iter == m_descriptor_cache.end()){
14095
break;
@@ -158,7 +113,6 @@ JsonValue ControllerOption::to_json() const{
158113
JsonObject obj;
159114
obj["Interface"] = CONTROLLER_INTERFACE_STRINGS.get_string(m_descriptor->interface_type);
160115
obj["Controller"] = CONTROLLER_TYPE_STRINGS.get_string(m_controller_type);
161-
// obj["Parameters"] = m_descriptor->to_json();
162116

163117
for (const auto& item : m_descriptor_cache){
164118
obj[CONTROLLER_INTERFACE_STRINGS.get_string(item.first)] = item.second->to_json();

SerialPrograms/Source/NintendoSwitch/Controllers/NintendoSwitch_ProController.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ class ProController::KeyboardManager : public KeyboardInputController{
6565
deltas.to_state(static_cast<SwitchControllerState&>(state));
6666
}
6767
virtual void cancel_all_commands() override{
68-
m_controller.cancel_all_commands(nullptr);
68+
m_controller.cancel_all_commands();
6969
}
7070
virtual void replace_on_next_command() override{
71-
m_controller.replace_on_next_command(nullptr);
71+
m_controller.replace_on_next_command();
7272
}
7373
virtual void send_state(const ControllerState& state) override{
7474
const SwitchControllerState& switch_state = static_cast<const SwitchControllerState&>(state);

SerialPrograms/Source/NintendoSwitch/Controllers/NintendoSwitch_ProController.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ class ProController : public AbstractController{
9191

9292
// Cancel all commands. This returns the controller to the neutral button
9393
// state and clears the command queue.
94-
virtual void cancel_all_commands(const Cancellable* cancellable) = 0;
94+
virtual void cancel_all_commands() = 0;
9595

9696
// Declare that the next command will replace the current command stream
9797
// with no gaps.
98-
virtual void replace_on_next_command(const Cancellable* cancellable) = 0;
98+
virtual void replace_on_next_command() = 0;
9999

100100

101101
public:
@@ -340,7 +340,7 @@ class ProControllerContext final : public CancellableScope{
340340
void cancel_now(){
341341
m_lifetime_sanitizer.check_usage();
342342
CancellableScope::cancel(nullptr);
343-
m_controller.cancel_all_commands(this);
343+
m_controller.cancel_all_commands();
344344
}
345345

346346
// Stop the commands in this context, but do it lazily.
@@ -354,7 +354,7 @@ class ProControllerContext final : public CancellableScope{
354354
void cancel_lazy(){
355355
m_lifetime_sanitizer.check_usage();
356356
CancellableScope::cancel(nullptr);
357-
m_controller.replace_on_next_command(this);
357+
m_controller.replace_on_next_command();
358358
}
359359

360360
virtual bool cancel(std::exception_ptr exception) noexcept override{
@@ -363,7 +363,7 @@ class ProControllerContext final : public CancellableScope{
363363
return true;
364364
}
365365
try{
366-
m_controller.cancel_all_commands(this);
366+
m_controller.cancel_all_commands();
367367
}catch (...){}
368368
return false;
369369
}

SerialPrograms/Source/NintendoSwitch/Controllers/NintendoSwitch_ProController_SerialPABotBase.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,14 @@ void ProController_SerialPABotBase::wait_for_all(const Cancellable* cancellable)
7979
m_serial->wait_for_all_requests(cancellable);
8080
// cout << "wait_for_all() - exit" << endl;
8181
}
82-
void ProController_SerialPABotBase::cancel_all_commands(const Cancellable* cancellable){
82+
void ProController_SerialPABotBase::cancel_all_commands(){
8383
if (!is_ready()){
8484
throw InvalidConnectionStateException();
8585
}
8686
m_serial->stop_all_commands();
8787
this->clear_on_next();
8888
}
89-
void ProController_SerialPABotBase::replace_on_next_command(const Cancellable* cancellable){
89+
void ProController_SerialPABotBase::replace_on_next_command(){
9090
if (!is_ready()){
9191
throw InvalidConnectionStateException();
9292
}

SerialPrograms/Source/NintendoSwitch/Controllers/NintendoSwitch_ProController_SerialPABotBase.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ class ProController_SerialPABotBase : public ProControllerWithScheduler{
3939
// General Control
4040

4141
virtual void wait_for_all(const Cancellable* cancellable) override;
42-
virtual void cancel_all_commands(const Cancellable* cancellable) override;
43-
virtual void replace_on_next_command(const Cancellable* cancellable) override;
42+
virtual void cancel_all_commands() override;
43+
virtual void replace_on_next_command() override;
4444

4545

4646
public:

SerialPrograms/Source/NintendoSwitch/Controllers/SysbotBase/SysbotBase_Connection.cpp

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ bool parse_ip_and_port(const std::string& str, QHostAddress& address, int& port)
4040
SysbotBaseNetwork_Connection::SysbotBaseNetwork_Connection(
4141
Logger& logger,
4242
const std::string& url
43-
){
43+
)
44+
: m_logger(logger)
45+
{
4446
if (!parse_ip_and_port(url, m_address, m_port)){
4547
set_status(html_color_text("Invalid IP address + port.", COLOR_RED));
4648
return;
@@ -55,9 +57,9 @@ SysbotBaseNetwork_Connection::~SysbotBaseNetwork_Connection(){
5557
m_stopping.store(true, std::memory_order_release);
5658
{
5759
std::lock_guard<std::mutex> lg(m_lock);
58-
if (m_socket){
59-
m_socket->abort();
60-
}
60+
// if (m_socket){
61+
// m_socket->abort();
62+
// }
6163
m_cv.notify_all();
6264
}
6365
if (m_thread.joinable()){
@@ -78,7 +80,13 @@ std::map<ControllerType, std::set<ControllerFeature>> SysbotBaseNetwork_Connecti
7880

7981
void SysbotBaseNetwork_Connection::write_data(const std::string& data){
8082
std::lock_guard<std::mutex> lg(m_lock);
83+
if (m_socket == nullptr){
84+
return;
85+
}
86+
// cout << "Sending: " << data << endl;
8187
qint64 written = m_socket->write(data.data(), data.size());
88+
m_socket->flush();
89+
// cout << "written = " << written << endl;
8290
if (written < 0 || written < (qint64)data.size()){
8391
m_ready.store(false, std::memory_order_release);
8492
m_stopping.store(true, std::memory_order_release);
@@ -94,21 +102,45 @@ void SysbotBaseNetwork_Connection::thread_body_wrapper(){
94102
std::lock_guard<std::mutex> lg(m_lock);
95103
m_socket = &socket;
96104
}
105+
#if 0
106+
thread_body_internal();
107+
#else
97108
try{
98109
thread_body_internal();
99-
std::lock_guard<std::mutex> lg(m_lock);
100-
m_socket = nullptr;
110+
}catch (Exception& e){
111+
try{
112+
global_logger_tagged().log("An exception was thrown from the network thread: " + e.to_str(), COLOR_RED);
113+
set_status(html_color_text("Error: Unhandled Exception", COLOR_RED));
114+
}catch (...){}
115+
}catch (std::exception& e){
116+
try{
117+
global_logger_tagged().log("An exception was thrown from the network thread: " + std::string(e.what()), COLOR_RED);
118+
set_status(html_color_text("Error: Unhandled Exception", COLOR_RED));
119+
}catch (...){}
101120
}catch (...){
102121
try{
103122
global_logger_tagged().log("An exception was thrown from the network thread.", COLOR_RED);
104123
set_status(html_color_text("Error: Unhandled Exception", COLOR_RED));
105124
}catch (...){}
106-
std::lock_guard<std::mutex> lg(m_lock);
107-
m_socket = nullptr;
108125
}
126+
#endif
127+
128+
try{
129+
m_socket->write("detachController\n");
130+
m_socket->flush();
131+
socket.close();
132+
}catch (...){}
133+
134+
std::lock_guard<std::mutex> lg(m_lock);
135+
m_socket = nullptr;
109136
}
110137
void SysbotBaseNetwork_Connection::thread_body_internal(){
111-
#if 0 // REMOVE
138+
std::string message =
139+
"Connecting To: " + m_address.toString().toStdString() +
140+
" - Port: " + std::to_string(m_port);
141+
142+
m_logger.log(message);
143+
#if 1
112144
m_socket->connect(
113145
m_socket, &QTcpSocket::disconnected,
114146
m_socket, [this]{
@@ -120,37 +152,52 @@ void SysbotBaseNetwork_Connection::thread_body_internal(){
120152
);
121153
#endif
122154

123-
m_socket->connect(
124-
m_socket, &QTcpSocket::disconnected,
125-
m_socket, [this]{
126-
m_stopping.store(true, std::memory_order_release);
127-
}
128-
);
129-
130155
m_socket->connectToHost(m_address, m_port);
131156

132157
WallClock start = current_time();
133158
WallClock deadline = start + std::chrono::seconds(30);
134159
while (true){
135160
if (current_time() > deadline){
161+
m_logger.log("Connection timed out.", COLOR_RED);
136162
set_status(html_color_text("Connection timed out.", COLOR_RED));
137163
return;
138164
}
139165
if (m_stopping.load(std::memory_order_acquire)){
166+
m_logger.log("Connection aborted.", COLOR_RED);
140167
return;
141168
}
142169
if (m_socket->waitForConnected(50)){
143170
break;
144171
}
145172
}
146173

174+
m_logger.log(message + " (Success)", COLOR_BLUE);
147175
set_status(html_color_text("Connected!", COLOR_BLUE));
148176

149177
declare_ready(supported_controllers());
150178

151-
// m_socket->write("press X\r\n");
152-
153-
179+
m_socket->write("configure mainLoopSleepTime 0\n");
180+
m_socket->flush();
181+
182+
//
183+
// This is stupid. Since we cannot block the constructor of this class to
184+
// wait for the connection, we spawn this thread to do the connection.
185+
// This thread is no longer needed once we've connected and have reported
186+
// the status.
187+
//
188+
// However, QTcpSocket doesn't like being constructed on one thread
189+
// and connecting out from another. So we construct it in this thread.
190+
// It also means we cannot destruct it until we're done using it. Thus we
191+
// must keep this thread alive until the entire class dies.
192+
//
193+
// If we ever need to receive packets from this connection, this would be
194+
// the thread to do it on.
195+
//
196+
197+
std::unique_lock<std::mutex> lg(m_lock);
198+
m_cv.wait(lg, [this]{
199+
return m_stopping.load(std::memory_order_relaxed);
200+
});
154201
}
155202

156203

SerialPrograms/Source/NintendoSwitch/Controllers/SysbotBase/SysbotBase_Connection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class SysbotBaseNetwork_Connection : public ControllerConnection{
3636
void thread_body_internal();
3737

3838
private:
39+
Logger& m_logger;
3940
QHostAddress m_address;
4041
int m_port;
4142

SerialPrograms/Source/NintendoSwitch/Controllers/SysbotBase/SysbotBase_Descriptor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
#include "SysbotBase_ProController.h"
1111
#include "SysbotBase_SelectorWidget.h"
1212

13+
//#include <iostream>
14+
//using std::cout;
15+
//using std::endl;
16+
1317
namespace PokemonAutomation{
1418

1519
template class InterfaceType_t<SysbotBase::SysbotBaseNetwork_Descriptor>;

0 commit comments

Comments
 (0)