Skip to content

Commit d559035

Browse files
committed
Key the ESP32 settings by MAC address.
1 parent a9df43b commit d559035

11 files changed

+365
-6
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/* MAC Address Option
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include <mutex>
8+
#include "Common/Cpp/Containers/Pimpl.tpp"
9+
#include "Common/Cpp/Json/JsonValue.h"
10+
#include "MacAddressOption.h"
11+
12+
#include "Common/Qt/Options/MacAddressWidget.h"
13+
14+
//#include <iostream>
15+
//using std::cout;
16+
//using std::endl;
17+
18+
namespace PokemonAutomation{
19+
20+
21+
22+
ConfigWidget* MacAddressCell::make_QtWidget(QWidget& parent){
23+
return new MacAddressCellWidget(parent, *this);
24+
}
25+
26+
27+
28+
std::string write_MAC_address(size_t length, const uint8_t* address){
29+
static const char HEX_DIGITS[] = "0123456789ABCDEF";
30+
std::string ret;
31+
for (size_t c = 0; c < length; c++){
32+
if (!ret.empty()){
33+
ret += "-";
34+
}
35+
ret += HEX_DIGITS[address[c] >> 4];
36+
ret += HEX_DIGITS[address[c] & 0xf];
37+
}
38+
return ret;
39+
}
40+
void parse_MAC_address(size_t length, uint8_t* address, const std::string& str){
41+
memset(address, 0, length);
42+
size_t current_index = 0;
43+
for (char ch : str){
44+
if (current_index >= 2*length){
45+
return;
46+
}
47+
if ('0' <= ch && ch <= '9'){
48+
ch -= '0';
49+
}else if ('a' <= ch && ch <= 'f'){
50+
ch += 10 - 'a';
51+
}else if ('A' <= ch && ch <= 'F'){
52+
ch += 10 - 'A';
53+
}else{
54+
continue;
55+
}
56+
address[current_index / 2] |= ch << 4*(1 - current_index % 2);
57+
current_index++;
58+
}
59+
}
60+
61+
62+
63+
struct MacAddressCell::Data{
64+
mutable std::mutex m_lock;
65+
std::vector<uint8_t> m_current;
66+
67+
Data(size_t bytes, const uint8_t* current)
68+
: m_current(bytes)
69+
{
70+
if (current != nullptr){
71+
memcpy(m_current.data(), current, bytes);
72+
}
73+
}
74+
};
75+
76+
77+
78+
MacAddressCell::~MacAddressCell() = default;
79+
MacAddressCell::MacAddressCell(const MacAddressCell& x)
80+
: ConfigOption(x)
81+
, m_data(CONSTRUCT_TOKEN, x.m_data->m_current.size(), x.m_data->m_current.data())
82+
{}
83+
void MacAddressCell::operator=(const MacAddressCell& x){
84+
if (bytes() != x.bytes()){
85+
throw InternalProgramError(
86+
nullptr, PA_CURRENT_FUNCTION,
87+
"Attempt to assign a MAC address is mismatching size."
88+
);
89+
}
90+
{
91+
std::scoped_lock<std::mutex, std::mutex> lg(m_data->m_lock, x.m_data->m_lock);
92+
memcpy(m_data->m_current.data(), x.m_data->m_current.data(), bytes());
93+
}
94+
report_value_changed(this);
95+
}
96+
MacAddressCell::MacAddressCell(
97+
LockMode lock_while_running,
98+
size_t bytes,
99+
uint8_t* current_value
100+
)
101+
: ConfigOption(lock_while_running)
102+
, m_data(CONSTRUCT_TOKEN, bytes, current_value)
103+
{}
104+
105+
106+
size_t MacAddressCell::bytes() const{
107+
return m_data->m_current.size();
108+
}
109+
std::string MacAddressCell::to_string() const{
110+
std::lock_guard<std::mutex> lg(m_data->m_lock);
111+
return write_MAC_address(m_data->m_current.size(), m_data->m_current.data());
112+
}
113+
void MacAddressCell::current_value(uint8_t* address) const{
114+
std::lock_guard<std::mutex> lg(m_data->m_lock);
115+
memcpy(address, m_data->m_current.data(), m_data->m_current.size());
116+
}
117+
void MacAddressCell::set(const uint8_t* address){
118+
{
119+
std::lock_guard<std::mutex> lg(m_data->m_lock);
120+
if (memcmp(m_data->m_current.data(), address, m_data->m_current.size()) == 0){
121+
return;
122+
}
123+
memcpy(m_data->m_current.data(), address, m_data->m_current.size());
124+
}
125+
report_value_changed(this);
126+
}
127+
void MacAddressCell::set(const std::string& address){
128+
std::vector<uint8_t> new_value(m_data->m_current.size());
129+
parse_MAC_address(new_value.size(), new_value.data(), address);
130+
set(new_value.data());
131+
}
132+
133+
134+
bool MacAddressCell::operator==(const uint8_t* address) const{
135+
std::lock_guard<std::mutex> lg(m_data->m_lock);
136+
return memcmp(m_data->m_current.data(), address, m_data->m_current.size()) == 0;
137+
}
138+
139+
140+
void MacAddressCell::load_json(const JsonValue& json){
141+
set(json.to_string_default());
142+
}
143+
JsonValue MacAddressCell::to_json() const{
144+
return to_string();
145+
}
146+
147+
148+
149+
150+
151+
}

Common/Cpp/Options/MacAddressOption.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/* MAC Address Option
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
* This option is thread-safe.
6+
*
7+
*/
8+
9+
#ifndef PokemonAutomation_Options_MacAddressOption_H
10+
#define PokemonAutomation_Options_MacAddressOption_H
11+
12+
#include "Common/Cpp/Containers/Pimpl.h"
13+
#include "ConfigOption.h"
14+
15+
namespace PokemonAutomation{
16+
17+
18+
std::string write_MAC_address(size_t length, const uint8_t* address);
19+
void parse_MAC_address(size_t length, uint8_t* address, const std::string& str);
20+
21+
22+
class MacAddressCell : public ConfigOption{
23+
public:
24+
~MacAddressCell();
25+
MacAddressCell(const MacAddressCell& x);
26+
void operator=(const MacAddressCell& x);
27+
MacAddressCell(
28+
LockMode lock_while_running,
29+
size_t bytes,
30+
uint8_t* current_value
31+
);
32+
33+
public:
34+
size_t bytes() const;
35+
std::string to_string() const;
36+
37+
// Buffer must be long enough.
38+
39+
void current_value(uint8_t* address) const;
40+
void set(const uint8_t* address);
41+
void set(const std::string& address);
42+
43+
bool operator==(const uint8_t* address) const;
44+
45+
virtual void load_json(const JsonValue& json) override;
46+
virtual JsonValue to_json() const override;
47+
48+
public:
49+
virtual ConfigWidget* make_QtWidget(QWidget& parent) override;
50+
51+
protected:
52+
struct Data;
53+
Pimpl<Data> m_data;
54+
};
55+
56+
57+
58+
59+
60+
61+
}
62+
#endif
63+

Common/Cpp/Options/SimpleIntegerOption.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class SimpleIntegerCell : public ConfigOption{
4747
Type current_value() const;
4848

4949
operator Type() const;
50-
virtual std::string set(Type x);
50+
std::string set(Type x);
5151

5252
virtual void load_json(const JsonValue& json) override;
5353
virtual JsonValue to_json() const override;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/* MAC Address Option
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include <QLineEdit>
8+
#include "ConfigWidget.h"
9+
#include "MacAddressWidget.h"
10+
11+
//#include <iostream>
12+
//using std::cout;
13+
//using std::endl;
14+
15+
namespace PokemonAutomation{
16+
17+
18+
MacAddressCellWidget::~MacAddressCellWidget(){
19+
m_value.remove_listener(*this);
20+
}
21+
22+
MacAddressCellWidget::MacAddressCellWidget(QWidget& parent, MacAddressCell& value)
23+
: QLineEdit(QString::fromStdString(value.to_string()), &parent)
24+
, ConfigWidget(value, *this)
25+
, m_value(value)
26+
{
27+
// cout << "sizeHint() = " << this->sizeHint().width() << endl;
28+
29+
this->setReadOnly(value.lock_mode() == LockMode::READ_ONLY);
30+
31+
connect(
32+
this, &QLineEdit::editingFinished,
33+
this, [this](){
34+
m_value.set(this->text().toStdString());
35+
}
36+
);
37+
value.add_listener(*this);
38+
}
39+
void MacAddressCellWidget::update_value(){
40+
this->setText(QString::fromStdString(m_value.to_string()));
41+
}
42+
void MacAddressCellWidget::value_changed(void* object){
43+
QMetaObject::invokeMethod(this, [this]{
44+
update_value();
45+
}, Qt::QueuedConnection);
46+
}
47+
48+
49+
50+
}

Common/Qt/Options/MacAddressWidget.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* MAC Address option
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_MacAddressWidget_H
8+
#define PokemonAutomation_MacAddressWidget_H
9+
10+
#include <QLineEdit>
11+
#include "ConfigWidget.h"
12+
#include "Common/Cpp/Options/MacAddressOption.h"
13+
14+
namespace PokemonAutomation{
15+
16+
17+
18+
19+
class MacAddressCellWidget : public QLineEdit, public ConfigWidget{
20+
public:
21+
~MacAddressCellWidget();
22+
MacAddressCellWidget(QWidget& parent, MacAddressCell& value);
23+
24+
virtual void update_value() override;
25+
virtual void value_changed(void* object) override;
26+
27+
private:
28+
MacAddressCell& m_value;
29+
};
30+
31+
32+
33+
34+
}
35+
#endif

SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase_PostConnectActions.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,32 @@ void run_post_connect_actions_ESP32(
3636
case ControllerType::NintendoSwitch_WirelessProController:
3737
case ControllerType::NintendoSwitch_LeftJoycon:
3838
case ControllerType::NintendoSwitch_RightJoycon:{
39+
uint8_t controller_mac_address[6] = {};
40+
{
41+
BotBaseMessage response = botbase.issue_request_and_wait(
42+
MessageControllerReadSpi(
43+
desired_controller,
44+
0x80000000, sizeof(controller_mac_address)
45+
),
46+
nullptr
47+
);
48+
if (response.body.size() == sizeof(seqnum_t) + sizeof(controller_mac_address)){
49+
memcpy(
50+
controller_mac_address,
51+
response.body.data() + sizeof(seqnum_t),
52+
sizeof(controller_mac_address)
53+
);
54+
}else{
55+
logger.log(
56+
"Invalid response size to PABB_MSG_ESP32_REQUEST_READ_SPI: body = " + std::to_string(response.body.size()),
57+
COLOR_RED
58+
);
59+
}
60+
}
61+
3962
NintendoSwitch::ControllerProfile profile =
4063
PokemonAutomation::NintendoSwitch::ConsoleSettings::instance().CONTROLLER_SETTINGS.get_or_make_profile(
64+
controller_mac_address,
4165
device_name,
4266
desired_controller
4367
);

0 commit comments

Comments
 (0)