Skip to content

Commit 80cfab8

Browse files
committed
Add infra to change controller types.
1 parent 588b8ea commit 80cfab8

16 files changed

+103
-46
lines changed

SerialPrograms/Source/Controllers/ControllerDescriptor.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ void InterfaceType::register_factory(
4141

4242

4343
ControllerOption::ControllerOption()
44-
: m_controller_type(ControllerType::None)
45-
, m_descriptor(new NullControllerDescriptor())
44+
: m_descriptor(new NullControllerDescriptor())
4645
{}
4746

4847

@@ -63,7 +62,6 @@ std::shared_ptr<const ControllerDescriptor> ControllerOption::get_descriptor_fro
6362

6463
void ControllerOption::load_json(const JsonValue& json){
6564
std::shared_ptr<const ControllerDescriptor> descriptor;
66-
ControllerType controller_type = ControllerType::None;
6765
do{
6866
if (json.is_null()){
6967
break;
@@ -77,10 +75,6 @@ void ControllerOption::load_json(const JsonValue& json){
7775
if (type == nullptr){
7876
break;
7977
}
80-
const std::string* controller = obj->get_string("Controller");
81-
if (controller != nullptr){
82-
controller_type = CONTROLLER_TYPE_STRINGS.get_enum(*controller, ControllerType::None);
83-
}
8478

8579
for (const auto& item : ALL_CONTROLLER_INTERFACES){
8680
const JsonValue* params = obj->get_value(CONTROLLER_INTERFACE_STRINGS.get_string(item.first));
@@ -104,15 +98,13 @@ void ControllerOption::load_json(const JsonValue& json){
10498
}
10599

106100
m_descriptor = std::move(descriptor);
107-
m_controller_type = controller_type;
108101
}
109102
JsonValue ControllerOption::to_json() const{
110103
if (!m_descriptor){
111104
return JsonValue();
112105
}
113106
JsonObject obj;
114107
obj["Interface"] = CONTROLLER_INTERFACE_STRINGS.get_string(m_descriptor->interface_type);
115-
obj["Controller"] = CONTROLLER_TYPE_STRINGS.get_string(m_controller_type);
116108

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

SerialPrograms/Source/Controllers/ControllerDescriptor.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#ifndef PokemonAutomation_Controllers_ControllerDescriptor_H
88
#define PokemonAutomation_Controllers_ControllerDescriptor_H
99

10+
#include <optional>
1011
#include <string>
1112
#include <memory>
1213
#include <map>
@@ -99,7 +100,10 @@ class ControllerDescriptor{
99100
virtual void load_json(const JsonValue& json) = 0;
100101
virtual JsonValue to_json() const = 0;
101102

102-
virtual std::unique_ptr<ControllerConnection> open_connection(Logger& logger) const = 0;
103+
virtual std::unique_ptr<ControllerConnection> open_connection(
104+
Logger& logger,
105+
std::optional<ControllerType> change_controller
106+
) const = 0;
103107
virtual std::unique_ptr<AbstractController> make_controller(
104108
Logger& logger,
105109
ControllerConnection& connection,
@@ -140,9 +144,6 @@ class ControllerOption{
140144
JsonValue to_json() const;
141145

142146

143-
public:
144-
// friend class ControllerSession;
145-
ControllerType m_controller_type;
146147
private:
147148
std::shared_ptr<const ControllerDescriptor> m_descriptor;
148149

SerialPrograms/Source/Controllers/ControllerSession.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ ControllerSession::ControllerSession(
4848
: m_logger(logger)
4949
, m_requirements(requirements)
5050
, m_option(option)
51+
, m_controller_type(ControllerType::None)
5152
, m_options_locked(false)
52-
, m_connection_is_shutting_down(false)
5353
, m_descriptor(option.descriptor())
54-
, m_connection(m_descriptor->open_connection(logger))
54+
, m_connection(m_descriptor->open_connection(logger, {}))
5555
{
5656
if (!m_connection){
5757
return;
@@ -102,7 +102,7 @@ std::shared_ptr<const ControllerDescriptor> ControllerSession::descriptor() cons
102102
}
103103
ControllerType ControllerSession::controller_type() const{
104104
std::lock_guard<std::mutex> lg(m_state_lock);
105-
return m_option.m_controller_type;
105+
return m_controller_type;
106106
}
107107
std::string ControllerSession::status_text() const{
108108
std::lock_guard<std::mutex> lg(m_state_lock);
@@ -166,13 +166,13 @@ void ControllerSession::set_options_locked(bool locked){
166166
}
167167

168168

169-
void ControllerSession::make_controller(){
169+
void ControllerSession::make_controller(std::optional<ControllerType> change_controller){
170170
// Must be called under "m_reset_lock".
171171

172172
bool ready = false;
173173
{
174174
std::lock_guard<std::mutex> lg(m_state_lock);
175-
m_connection = m_descriptor->open_connection(m_logger);
175+
m_connection = m_descriptor->open_connection(m_logger, change_controller);
176176
if (m_connection){
177177
m_connection->add_status_listener(*this);
178178
ready = m_connection->is_ready();
@@ -222,7 +222,7 @@ bool ControllerSession::set_device(const std::shared_ptr<const ControllerDescrip
222222
controller.reset();
223223
connection.reset();
224224

225-
make_controller();
225+
make_controller({});
226226
}
227227
signal_descriptor_changed(device);
228228
signal_status_text_changed(status_text());
@@ -242,15 +242,15 @@ bool ControllerSession::set_controller(ControllerType controller_type){
242242
if (m_options_locked){
243243
return false;
244244
}
245-
if (m_option.m_controller_type == controller_type){
245+
if (m_controller_type == controller_type){
246246
return true;
247247
}
248248

249249
// Move these out to indicate that we should no longer access them.
250250
controller = std::move(m_controller);
251251
connection = std::move(m_connection);
252252

253-
m_option.m_controller_type = controller_type;
253+
m_controller_type = controller_type;
254254
}
255255

256256
// With the lock released, it is now safe to destroy them.
@@ -259,7 +259,7 @@ bool ControllerSession::set_controller(ControllerType controller_type){
259259
controller.reset();
260260
connection.reset();
261261

262-
make_controller();
262+
make_controller(controller_type);
263263
device = m_descriptor;
264264
}
265265
signal_descriptor_changed(device);
@@ -296,7 +296,7 @@ std::string ControllerSession::reset(){
296296
controller.reset();
297297
connection.reset();
298298

299-
make_controller();
299+
make_controller(m_controller_type);
300300
}
301301
signal_status_text_changed(status_text());
302302
return "";
@@ -377,7 +377,7 @@ void ControllerSession::post_connection_ready(
377377

378378
// Commit all changes.
379379
// cout << "current_controller = " << CONTROLLER_TYPE_STRINGS.get_string(current_controller) << endl;
380-
m_option.m_controller_type = current_controller;
380+
m_controller_type = current_controller;
381381
ready = m_controller && m_controller->is_ready();
382382

383383
WriteSpinLock lg1(m_message_lock);

SerialPrograms/Source/Controllers/ControllerSession.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class ControllerSession : private ControllerConnection::StatusListener{
118118

119119

120120
private:
121-
void make_controller();
121+
void make_controller(std::optional<ControllerType> change_controller);
122122

123123
// virtual void pre_connection_not_ready(ControllerConnection& connection) override;
124124
virtual void post_connection_ready(
@@ -150,12 +150,12 @@ class ControllerSession : private ControllerConnection::StatusListener{
150150
Logger& m_logger;
151151
const ControllerRequirements& m_requirements;
152152
ControllerOption& m_option;
153+
ControllerType m_controller_type;
153154

154155
std::mutex m_reset_lock;
155156
mutable std::mutex m_state_lock;
156157

157158
bool m_options_locked;
158-
std::atomic<bool> m_connection_is_shutting_down;
159159
std::string m_user_input_disallow_reason;
160160

161161
SpinLock m_message_lock;

SerialPrograms/Source/Controllers/NullController.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ void NullControllerDescriptor::load_json(const JsonValue& json){
2828
JsonValue NullControllerDescriptor::to_json() const{
2929
return JsonValue();
3030
}
31-
std::unique_ptr<ControllerConnection> NullControllerDescriptor::open_connection(Logger& logger) const{
31+
std::unique_ptr<ControllerConnection> NullControllerDescriptor::open_connection(
32+
Logger& logger,
33+
std::optional<ControllerType> change_controller
34+
) const{
3235
return nullptr;
3336
}
3437
std::unique_ptr<AbstractController> NullControllerDescriptor::make_controller(

SerialPrograms/Source/Controllers/NullController.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ class NullControllerDescriptor : public ControllerDescriptor{
2626
virtual void load_json(const JsonValue& json) override;
2727
virtual JsonValue to_json() const override;
2828

29-
virtual std::unique_ptr<ControllerConnection> open_connection(Logger& logger) const override;
29+
virtual std::unique_ptr<ControllerConnection> open_connection(
30+
Logger& logger,
31+
std::optional<ControllerType> change_controller
32+
) const override;
3033
virtual std::unique_ptr<AbstractController> make_controller(
3134
Logger& logger,
3235
ControllerConnection& connection,

SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ std::string program_name(uint8_t id){
3131
default: return "Unknown ID";
3232
}
3333
}
34-
ControllerType controller_type(uint32_t id){
34+
ControllerType id_to_controller_type(uint32_t id){
3535
switch (id){
3636
case PABB_CID_NONE:
3737
return ControllerType::None;
@@ -47,6 +47,20 @@ ControllerType controller_type(uint32_t id){
4747
return ControllerType::None;
4848
}
4949
}
50+
uint32_t controller_type_to_id(ControllerType controller_type){
51+
switch (controller_type){
52+
case ControllerType::NintendoSwitch_WiredProController:
53+
return PABB_CID_NINTENDO_SWITCH_WIRED_PRO_CONTROLLER;
54+
case ControllerType::NintendoSwitch_WirelessProController:
55+
return PABB_CID_NINTENDO_SWITCH_WIRELESS_PRO_CONTROLLER;
56+
case ControllerType::NintendoSwitch_LeftJoycon:
57+
return PABB_CID_NINTENDO_SWITCH_LEFT_JOYCON;
58+
case ControllerType::NintendoSwitch_RightJoycon:
59+
return PABB_CID_NINTENDO_SWITCH_RIGHT_JOYCON;
60+
default:
61+
return PABB_CID_NONE;
62+
}
63+
}
5064

5165

5266

SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ extern const ControllerRequirements OLD_NINTENDO_SWITCH_DEFAULT_REQUIREMENTS;
2424

2525

2626
std::string program_name(uint8_t id);
27-
ControllerType controller_type(uint32_t id);
27+
ControllerType id_to_controller_type(uint32_t id);
28+
uint32_t controller_type_to_id(ControllerType controller_type);
2829

2930

3031

SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase_Connection.cpp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "Common/Cpp/Exceptions.h"
1111
#include "Common/Cpp/PanicDump.h"
1212
#include "Common/Microcontroller/DeviceRoutines.h"
13+
#include "Common/PokemonSwSh/PokemonProgramIDs.h"
1314
#include "ClientSource/Libraries/MessageConverter.h"
1415
#include "ClientSource/Connection/SerialConnection.h"
1516
#include "ClientSource/Connection/PABotBase.h"
@@ -32,7 +33,8 @@ namespace SerialPABotBase{
3233

3334
SerialPABotBase_Connection::SerialPABotBase_Connection(
3435
Logger& logger,
35-
const QSerialPortInfo* port
36+
const QSerialPortInfo* port,
37+
std::optional<ControllerType> change_controller
3638
)
3739
: m_logger(logger, GlobalSettings::instance().LOG_EVERYTHING)
3840
{
@@ -78,7 +80,11 @@ SerialPABotBase_Connection::SerialPABotBase_Connection(
7880
return;
7981
}
8082

81-
m_status_thread = std::thread(run_with_catch, "SerialPABotBase_Connection::thread_body()", [this]{ thread_body(); });
83+
m_status_thread = std::thread(
84+
run_with_catch,
85+
"SerialPABotBase_Connection::thread_body()",
86+
[=, this]{ thread_body(change_controller); }
87+
);
8288
}
8389
SerialPABotBase_Connection::~SerialPABotBase_Connection(){
8490
m_ready.store(false, std::memory_order_release);
@@ -144,7 +150,9 @@ ControllerModeStatus SerialPABotBase_Connection::controller_mode_status() const{
144150
}
145151

146152

147-
ControllerModeStatus SerialPABotBase_Connection::read_device_specs(){
153+
ControllerModeStatus SerialPABotBase_Connection::read_device_specs(
154+
std::optional<ControllerType> change_controller
155+
){
148156
Logger& logger = m_logger;
149157

150158

@@ -196,16 +204,34 @@ ControllerModeStatus SerialPABotBase_Connection::read_device_specs(){
196204
current_controller = program_iter->second.begin()->first;
197205
}else if (program_iter->second.size() > 1){
198206
uint32_t type_id = Microcontroller::read_controller_mode(*m_botbase);
199-
current_controller = controller_type(type_id);
207+
current_controller = id_to_controller_type(type_id);
200208
}
201209
logger.log("Reading Controller Mode... Mode = " + CONTROLLER_TYPE_STRINGS.get_string(current_controller));
202210

211+
212+
if (change_controller && program_iter->second.size() > 1){
213+
ControllerType desired_controller = change_controller.value();
214+
uint32_t native_controller_id = controller_type_to_id(desired_controller);
215+
m_botbase->issue_request_and_wait(
216+
Microcontroller::DeviceRequest_change_controller_mode(native_controller_id),
217+
nullptr
218+
);
219+
220+
// Re-read the controller.
221+
logger.log("Reading Controller Mode...");
222+
uint32_t type_id = Microcontroller::read_controller_mode(*m_botbase);
223+
current_controller = id_to_controller_type(type_id);
224+
logger.log("Reading Controller Mode... Mode = " + CONTROLLER_TYPE_STRINGS.get_string(current_controller));
225+
}
226+
203227
return {current_controller, program_iter->second};
204228
}
205229

206230

207231

208-
void SerialPABotBase_Connection::thread_body(){
232+
void SerialPABotBase_Connection::thread_body(
233+
std::optional<ControllerType> change_controller
234+
){
209235
using namespace PokemonAutomation;
210236

211237
m_botbase->set_sniffer(&m_logger);
@@ -236,7 +262,7 @@ void SerialPABotBase_Connection::thread_body(){
236262
ControllerModeStatus mode_status;
237263
std::string error;
238264
try{
239-
mode_status = read_device_specs();
265+
mode_status = read_device_specs(change_controller);
240266
std::lock_guard<std::mutex> lg(m_lock);
241267
m_mode_status = mode_status;
242268

SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase_Connection.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ class SerialPABotBase_Connection : public ControllerConnection{
2626
public:
2727
SerialPABotBase_Connection(
2828
Logger& logger,
29-
const QSerialPortInfo* port
29+
const QSerialPortInfo* port,
30+
std::optional<ControllerType> change_controller
3031
);
3132
~SerialPABotBase_Connection();
3233

@@ -42,9 +43,13 @@ class SerialPABotBase_Connection : public ControllerConnection{
4243

4344

4445
private:
45-
ControllerModeStatus read_device_specs();
46+
ControllerModeStatus read_device_specs(
47+
std::optional<ControllerType> change_controller
48+
);
4649

47-
void thread_body();
50+
void thread_body(
51+
std::optional<ControllerType> change_controller
52+
);
4853

4954

5055
private:

0 commit comments

Comments
 (0)