refactor: prefix private data members with m_

Rename all trailing-underscore private data members to the m_ prefix
required by AGENTS.md, across the auth, crypto, gip, mt76, and usb
transport classes plus the app session classes. Pure rename; no
behavior change. Full build and test suite pass.

Co-Authored-By: qwen3.8-27b@q3_k_xl: renamed members to m_ prefix
This commit is contained in:
portersky
2026-08-29 14:36:28 +02:00
parent ae9c71d76e
commit dfe7e8b87d
12 changed files with 329 additions and 329 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ if(NOT CMAKE_GENERATOR MATCHES "^(Ninja|Xcode)$")
endif() endif()
cmake_minimum_required(VERSION 3.21) cmake_minimum_required(VERSION 3.21)
project(xone_macos VERSION 0.1.19 LANGUAGES CXX Swift) project(xone_macos VERSION 0.1.20 LANGUAGES CXX Swift)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+9 -9
View File
@@ -79,15 +79,15 @@ private:
auto handle_pubkey(std::span<u8 const> data) -> int; auto handle_pubkey(std::span<u8 const> data) -> int;
auto get_transcript() -> std::array<u8, k_transcript_len>; auto get_transcript() -> std::array<u8, k_transcript_len>;
auth_sink& sink_; auth_sink& m_sink;
sha256 transcript_; sha256 m_transcript;
u8 last_sent_command_ = 0; u8 m_last_sent_command = 0;
std::array<u8, k_random_len> random_host_{}; std::array<u8, k_random_len> m_random_host{};
std::array<u8, k_random_len> random_client_{}; std::array<u8, k_random_len> m_random_client{};
std::array<u8, k_pubkey_len> pubkey_client_{}; std::array<u8, k_pubkey_len> m_pubkey_client{};
std::array<u8, k_pubkey2_len> pubkey_client2_{}; std::array<u8, k_pubkey2_len> m_pubkey_client2{};
std::array<u8, k_secret_len> master_secret_{}; std::array<u8, k_secret_len> m_master_secret{};
enum class deferred_action { enum class deferred_action {
none, none,
@@ -95,7 +95,7 @@ private:
exchange_ecdh, exchange_ecdh,
complete, complete,
}; };
deferred_action deferred_action_ = deferred_action::none; deferred_action m_deferred_action = deferred_action::none;
}; };
} // namespace xone::auth } // namespace xone::auth
+3 -3
View File
@@ -48,7 +48,7 @@ public:
auto finalize(std::array<u8, k_sha256_len>& out) -> void; auto finalize(std::array<u8, k_sha256_len>& out) -> void;
private: private:
CC_SHA256_CTX ctx_; CC_SHA256_CTX m_ctx;
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@@ -62,8 +62,8 @@ public:
auto finalize(std::array<u8, k_sha256_len>& out) -> void; auto finalize(std::array<u8, k_sha256_len>& out) -> void;
private: private:
sha256 inner_; sha256 m_inner;
sha256 outer_; sha256 m_outer;
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
+29 -29
View File
@@ -164,11 +164,11 @@ class client : public xone::auth::auth_sink {
public: public:
client(adapter& adapter, u8 id); client(adapter& adapter, u8 id);
auto id() const -> u8 { return id_; } auto id() const -> u8 { return m_id; }
auto hardware() const -> gip_hardware const& { return hardware_; } auto hardware() const -> gip_hardware const& { return m_hardware; }
auto audio_config_in() const -> gip_audio_config const& { return audio_config_in_; } auto audio_config_in() const -> gip_audio_config const& { return m_audio_config_in; }
auto audio_config_out() const -> gip_audio_config const& { return audio_config_out_; } auto audio_config_out() const -> gip_audio_config const& { return m_audio_config_out; }
auto classes() const -> std::vector<std::string> const& { return classes_; } auto classes() const -> std::vector<std::string> const& { return m_classes; }
auto has_interface(xone::guid_t const& guid) const -> bool; auto has_interface(xone::guid_t const& guid) const -> bool;
@@ -187,35 +187,35 @@ public:
auto send(std::span<u8 const> pkt, bool acknowledge) -> int override; auto send(std::span<u8 const> pkt, bool acknowledge) -> int override;
auto set_encryption_key(std::span<u8 const> key) -> int override; auto set_encryption_key(std::span<u8 const> key) -> int override;
auto start_auth() -> int { return auth_.start(); } auto start_auth() -> int { return m_auth.start(); }
auto process_auth(std::span<u8 const> data) -> int auto process_auth(std::span<u8 const> data) -> int
{ {
return auth_.process_pkt(data); return m_auth.process_pkt(data);
} }
private: private:
friend class adapter; friend class adapter;
adapter& adapter_; adapter& m_adapter;
u8 id_; u8 m_id;
gip_hardware hardware_{}; gip_hardware m_hardware{};
struct info_element { struct info_element {
u8 count = 0; u8 count = 0;
std::vector<u8> data; std::vector<u8> data;
}; };
std::unique_ptr<info_element> client_commands_; std::unique_ptr<info_element> m_client_commands;
std::unique_ptr<info_element> firmware_versions_; std::unique_ptr<info_element> m_firmware_versions;
std::unique_ptr<info_element> audio_formats_; std::unique_ptr<info_element> m_audio_formats;
std::unique_ptr<info_element> capabilities_out_; std::unique_ptr<info_element> m_capabilities_out;
std::unique_ptr<info_element> capabilities_in_; std::unique_ptr<info_element> m_capabilities_in;
std::vector<std::string> classes_; std::vector<std::string> m_classes;
std::unique_ptr<info_element> interfaces_; std::unique_ptr<info_element> m_interfaces;
std::unique_ptr<info_element> hid_descriptor_; std::unique_ptr<info_element> m_hid_descriptor;
gip_audio_config audio_config_in_; gip_audio_config m_audio_config_in;
gip_audio_config audio_config_out_; gip_audio_config m_audio_config_out;
// Chunk reassembly buffers (large packets are split into chunks). // Chunk reassembly buffers (large packets are split into chunks).
struct chunk_buffer { struct chunk_buffer {
@@ -223,10 +223,10 @@ private:
u32 length = 0; u32 length = 0;
std::vector<u8> data; std::vector<u8> data;
}; };
std::unique_ptr<chunk_buffer> chunk_buf_out_; std::unique_ptr<chunk_buffer> m_chunk_buf_out;
std::unique_ptr<chunk_buffer> chunk_buf_in_; std::unique_ptr<chunk_buffer> m_chunk_buf_in;
xone::auth::auth auth_{*this}; xone::auth::auth m_auth{*this};
}; };
class adapter { class adapter {
@@ -288,13 +288,13 @@ private:
auto parse_hid_descriptor(client& c, u16 const offsets[8], auto parse_hid_descriptor(client& c, u16 const offsets[8],
std::span<u8 const> data) -> int; std::span<u8 const> data) -> int;
transport& transport_; transport& m_transport;
client_listener& listener_; client_listener& m_listener;
int audio_packet_count_; int m_audio_packet_count;
std::array<std::unique_ptr<client>, k_max_clients> clients_; std::array<std::unique_ptr<client>, k_max_clients> m_clients;
u8 data_sequence_ = 0; u8 m_data_sequence = 0;
u8 audio_sequence_ = 0; u8 m_audio_sequence = 0;
}; };
} // namespace xone::gip } // namespace xone::gip
+3 -3
View File
@@ -137,10 +137,10 @@ private:
auto write_beacon(bool pair) -> int; auto write_beacon(bool pair) -> int;
auto set_channel_candidates() -> int; auto set_channel_candidates() -> int;
usb::transport &transport_; usb::transport &m_transport;
char build_time_[17] = {}; char build_time_[17] = {};
std::array<channel, num_channels> channels_{}; std::array<channel, num_channels> m_channels{};
channel current_channel_{}; channel m_current_channel{};
}; };
} // namespace xone::mt76 } // namespace xone::mt76
+1 -1
View File
@@ -125,7 +125,7 @@ private:
static void on_read_completion(void *refcon, std::int32_t result, void *arg0); static void on_read_completion(void *refcon, std::int32_t result, void *arg0);
static void on_dongle_terminated(void *refcon, std::uint32_t iter); static void on_dongle_terminated(void *refcon, std::uint32_t iter);
std::unique_ptr<state> state_; std::unique_ptr<state> m_state;
}; };
// TRUE if an Xbox Wireless Dongle is connected (any supported PID). // TRUE if an Xbox Wireless Dongle is connected (any supported PID).
+34 -34
View File
@@ -30,29 +30,29 @@ class controller_transport : public xone::gip::transport {
public: public:
controller_transport(xone::mt76::chip& chip, std::uint8_t wcid, controller_transport(xone::mt76::chip& chip, std::uint8_t wcid,
std::array<std::uint8_t, 6> mac) std::array<std::uint8_t, 6> mac)
: chip_(chip) : m_chip(chip)
, wcid_(wcid) , m_wcid(wcid)
, mac_(mac) , m_mac(mac)
{ {
} }
auto send_frame(std::span<std::uint8_t const> frame) -> int override; auto send_frame(std::span<std::uint8_t const> frame) -> int override;
auto set_encryption_key(std::uint8_t client_id, auto set_encryption_key(std::uint8_t client_id,
std::span<std::uint8_t const> key) -> int override; std::span<std::uint8_t const> key) -> int override;
auto enable_encryption() -> void { encrypted_ = true; } auto enable_encryption() -> void { m_encrypted = true; }
private: private:
xone::mt76::chip& chip_; xone::mt76::chip& m_chip;
std::uint8_t wcid_; std::uint8_t m_wcid;
std::array<std::uint8_t, 6> mac_; std::array<std::uint8_t, 6> m_mac;
bool encrypted_ = false; bool m_encrypted = false;
}; };
class controller_listener : public xone::gip::client_listener { class controller_listener : public xone::gip::client_listener {
public: public:
controller_listener(xone_dongle& dongle, controller& controller) controller_listener(xone_dongle& dongle, controller& controller)
: dongle_(dongle) : m_dongle(dongle)
, controller_(controller) , m_controller(controller)
{ {
} }
@@ -63,8 +63,8 @@ public:
-> void override; -> void override;
private: private:
xone_dongle& dongle_; xone_dongle& m_dongle;
controller& controller_; controller& m_controller;
}; };
// One connected controller (tracked for the GUI). Guarded by xone_dongle's // One connected controller (tracked for the GUI). Guarded by xone_dongle's
@@ -163,14 +163,14 @@ auto firmware_path_for(std::uint16_t) -> std::string
auto controller_transport::send_frame(std::span<std::uint8_t const> frame) auto controller_transport::send_frame(std::span<std::uint8_t const> frame)
-> int -> int
{ {
return chip_.send_client_frame(wcid_, mac_, frame, encrypted_); return m_chip.send_client_frame(m_wcid, m_mac, frame, m_encrypted);
} }
auto controller_transport::set_encryption_key( auto controller_transport::set_encryption_key(
std::uint8_t client_id, std::span<std::uint8_t const> key) -> int std::uint8_t client_id, std::span<std::uint8_t const> key) -> int
{ {
(void)client_id; (void)client_id;
return chip_.set_client_key(wcid_, key); return m_chip.set_client_key(m_wcid, key);
} }
auto controller_listener::on_client_added(xone::gip::client& client) -> void auto controller_listener::on_client_added(xone::gip::client& client) -> void
@@ -181,24 +181,24 @@ auto controller_listener::on_client_added(xone::gip::client& client) -> void
return; return;
} }
std::lock_guard<std::mutex> guard(dongle_.lock); std::lock_guard<std::mutex> guard(m_dongle.lock);
controller_.gip_ready = true; m_controller.gip_ready = true;
xone::log_msg(xone::log_level::info, xone::log_msg(xone::log_level::info,
"api: GIP ready (wcid=%d)", controller_.wcid); "api: GIP ready (wcid=%d)", m_controller.wcid);
} }
auto controller_listener::on_client_removed(std::uint8_t) -> void auto controller_listener::on_client_removed(std::uint8_t) -> void
{ {
std::lock_guard<std::mutex> guard(dongle_.lock); std::lock_guard<std::mutex> guard(m_dongle.lock);
controller_.gip_ready = false; m_controller.gip_ready = false;
controller_.input_active = false; m_controller.input_active = false;
} }
auto controller_listener::on_guide_button(xone::gip::client&, bool down) auto controller_listener::on_guide_button(xone::gip::client&, bool down)
-> void -> void
{ {
std::lock_guard<std::mutex> guard(dongle_.lock); std::lock_guard<std::mutex> guard(m_dongle.lock);
controller_.guide_down = down; m_controller.guide_down = down;
} }
auto controller_listener::on_input( auto controller_listener::on_input(
@@ -208,24 +208,24 @@ auto controller_listener::on_input(
if (data.size() < 14) if (data.size() < 14)
return; return;
std::lock_guard<std::mutex> guard(dongle_.lock); std::lock_guard<std::mutex> guard(m_dongle.lock);
controller_.buttons = xone::load_le16(data.data()); m_controller.buttons = xone::load_le16(data.data());
controller_.trigger_left = xone::load_le16(data.data() + 2); m_controller.trigger_left = xone::load_le16(data.data() + 2);
controller_.trigger_right = xone::load_le16(data.data() + 4); m_controller.trigger_right = xone::load_le16(data.data() + 4);
controller_.stick_left_x = static_cast<std::int16_t>( m_controller.stick_left_x = static_cast<std::int16_t>(
xone::load_le16(data.data() + 6)); xone::load_le16(data.data() + 6));
controller_.stick_left_y = static_cast<std::int16_t>( m_controller.stick_left_y = static_cast<std::int16_t>(
~xone::load_le16(data.data() + 8)); ~xone::load_le16(data.data() + 8));
controller_.stick_right_x = static_cast<std::int16_t>( m_controller.stick_right_x = static_cast<std::int16_t>(
xone::load_le16(data.data() + 10)); xone::load_le16(data.data() + 10));
controller_.stick_right_y = static_cast<std::int16_t>( m_controller.stick_right_y = static_cast<std::int16_t>(
~xone::load_le16(data.data() + 12)); ~xone::load_le16(data.data() + 12));
++controller_.input_sequence; ++m_controller.input_sequence;
controller_.input_active = true; m_controller.input_active = true;
xone::log_msg(xone::log_level::debug, xone::log_msg(xone::log_level::debug,
"api: input wcid=%d buttons=0x%04x lt=%d rt=%d", "api: input wcid=%d buttons=0x%04x lt=%d rt=%d",
controller_.wcid, controller_.buttons, m_controller.wcid, m_controller.buttons,
controller_.trigger_left, controller_.trigger_right); m_controller.trigger_left, m_controller.trigger_right);
} }
auto xone_dongle::setup_controller(controller& c) -> void auto xone_dongle::setup_controller(controller& c) -> void
+37 -37
View File
@@ -141,7 +141,7 @@ struct pkt2_client_pubkey {
} // namespace } // namespace
auth::auth(auth_sink& sink) auth::auth(auth_sink& sink)
: sink_(sink) : m_sink(sink)
{ {
} }
@@ -192,14 +192,14 @@ auto auth::send_pkt(u8 cmd, void const* pkt, std::size_t len) -> int
hdr->data.version = cmd >= cmd2_host_hello ? 0x02 : 0x01; hdr->data.version = cmd >= cmd2_host_hello ? 0x02 : 0x01;
store_be16(&hdr->data.length, static_cast<u16>(data_len - sizeof(hdr->data))); store_be16(&hdr->data.length, static_cast<u16>(data_len - sizeof(hdr->data)));
last_sent_command_ = cmd; m_last_sent_command = cmd;
log_msg(log_level::debug, log_msg(log_level::debug,
"auth: tx command=0x%02x data_length=%u acknowledge=1", "auth: tx command=0x%02x data_length=%u acknowledge=1",
cmd, data_len); cmd, data_len);
transcript_.update( m_transcript.update(
{reinterpret_cast<u8 const*>(hdr) + sizeof(hdr->handshake), data_len}); {reinterpret_cast<u8 const*>(hdr) + sizeof(hdr->handshake), data_len});
return sink_.send({reinterpret_cast<u8 const*>(hdr), len}, true); return m_sink.send({reinterpret_cast<u8 const*>(hdr), len}, true);
} }
auto auth::request_pkt(u8 cmd, std::uint16_t len) -> int auto auth::request_pkt(u8 cmd, std::uint16_t len) -> int
@@ -216,14 +216,14 @@ auto auth::request_pkt(u8 cmd, std::uint16_t len) -> int
log_msg(log_level::debug, log_msg(log_level::debug,
"auth: tx request command=0x%02x data_length=%u acknowledge=1", "auth: tx request command=0x%02x data_length=%u acknowledge=1",
cmd, data_len); cmd, data_len);
return sink_.send({reinterpret_cast<u8 const*>(&req), sizeof(req)}, true); return m_sink.send({reinterpret_cast<u8 const*>(&req), sizeof(req)}, true);
} }
auto auth::send_hello() -> int auto auth::send_hello() -> int
{ {
pkt_host_hello pkt{}; pkt_host_hello pkt{};
random_bytes(random_host_); random_bytes(m_random_host);
std::memcpy(pkt.random.data(), random_host_.data(), k_random_len); std::memcpy(pkt.random.data(), m_random_host.data(), k_random_len);
return send_pkt(cmd_host_hello, &pkt.header, sizeof(pkt)); return send_pkt(cmd_host_hello, &pkt.header, sizeof(pkt));
} }
@@ -231,7 +231,7 @@ auto auth::send_finish(u8 cmd) -> int
{ {
pkt_host_finish pkt{}; pkt_host_finish pkt{};
auto transcript = get_transcript(); auto transcript = get_transcript();
prf_sha256(master_secret_, "Host Finished", transcript, pkt.transcript); prf_sha256(m_master_secret, "Host Finished", transcript, pkt.transcript);
return send_pkt(cmd, &pkt.header, sizeof(pkt)); return send_pkt(cmd, &pkt.header, sizeof(pkt));
} }
@@ -240,12 +240,12 @@ auto auth::send_complete() -> int
header_control hdr{}; header_control hdr{};
hdr.context = ctx_control; hdr.context = ctx_control;
hdr.control = ctrl_complete; hdr.control = ctrl_complete;
return sink_.send({reinterpret_cast<u8 const*>(&hdr), sizeof(hdr)}, false); return m_sink.send({reinterpret_cast<u8 const*>(&hdr), sizeof(hdr)}, false);
} }
auto auth::get_transcript() -> std::array<u8, k_transcript_len> auto auth::get_transcript() -> std::array<u8, k_transcript_len>
{ {
sha256 snap = transcript_; sha256 snap = m_transcript;
std::array<u8, k_transcript_len> out{}; std::array<u8, k_transcript_len> out{};
snap.finalize(out); snap.finalize(out);
return out; return out;
@@ -257,20 +257,20 @@ auto auth::exchange_rsa() -> void
std::array<u8, k_random_len * 2> random{}; std::array<u8, k_random_len * 2> random{};
std::array<u8, k_secret_len> pms{}; std::array<u8, k_secret_len> pms{};
std::copy(random_host_.begin(), random_host_.end(), random.begin()); std::copy(m_random_host.begin(), m_random_host.end(), random.begin());
std::copy(random_client_.begin(), random_client_.end(), std::copy(m_random_client.begin(), m_random_client.end(),
random.begin() + k_random_len); random.begin() + k_random_len);
random_bytes(pms); random_bytes(pms);
std::array<u8, k_encrypted_pms_len> encrypted{}; std::array<u8, k_encrypted_pms_len> encrypted{};
if (!rsa_encrypt_pkcs1(pubkey_client_, pms, encrypted)) { if (!rsa_encrypt_pkcs1(m_pubkey_client, pms, encrypted)) {
log_msg(log_level::error, "auth: encrypt RSA failed"); log_msg(log_level::error, "auth: encrypt RSA failed");
return; return;
} }
std::memcpy(pkt.encrypted_pms.data(), encrypted.data(), k_encrypted_pms_len); std::memcpy(pkt.encrypted_pms.data(), encrypted.data(), k_encrypted_pms_len);
prf_sha256(pms, "Master Secret", random, master_secret_); prf_sha256(pms, "Master Secret", random, m_master_secret);
if (send_pkt(cmd_host_secret, &pkt.header, sizeof(pkt))) if (send_pkt(cmd_host_secret, &pkt.header, sizeof(pkt)))
log_msg(log_level::error, "auth: send pkt failed"); log_msg(log_level::error, "auth: send pkt failed");
@@ -282,8 +282,8 @@ auto auth::exchange_ecdh() -> void
std::array<u8, k_random_len * 2> random{}; std::array<u8, k_random_len * 2> random{};
std::array<u8, k_secret2_len> secret{}; std::array<u8, k_secret2_len> secret{};
std::copy(random_host_.begin(), random_host_.end(), random.begin()); std::copy(m_random_host.begin(), m_random_host.end(), random.begin());
std::copy(random_client_.begin(), random_client_.end(), std::copy(m_random_client.begin(), m_random_client.end(),
random.begin() + k_random_len); random.begin() + k_random_len);
ec_scalar d{}; ec_scalar d{};
@@ -292,7 +292,7 @@ auto auth::exchange_ecdh() -> void
std::memcpy(pkt.pubkey.data(), q.data(), k_pubkey2_len); std::memcpy(pkt.pubkey.data(), q.data(), k_pubkey2_len);
ec_scalar shared_x{}; ec_scalar shared_x{};
if (!ec_compute_shared(d, pubkey_client2_, shared_x)) { if (!ec_compute_shared(d, m_pubkey_client2, shared_x)) {
log_msg(log_level::error, "auth: compute ECDH failed"); log_msg(log_level::error, "auth: compute ECDH failed");
return; return;
} }
@@ -302,7 +302,7 @@ auto auth::exchange_ecdh() -> void
h.update(shared_x); h.update(shared_x);
h.finalize(secret); h.finalize(secret);
prf_sha256(secret, "Master Secret", random, master_secret_); prf_sha256(secret, "Master Secret", random, m_master_secret);
if (send_pkt(cmd2_host_pubkey, &pkt.header, sizeof(pkt))) if (send_pkt(cmd2_host_pubkey, &pkt.header, sizeof(pkt)))
log_msg(log_level::error, "auth: send pkt failed"); log_msg(log_level::error, "auth: send pkt failed");
@@ -313,24 +313,24 @@ auto auth::complete_handshake() -> void
std::array<u8, k_random_len * 2> random{}; std::array<u8, k_random_len * 2> random{};
std::array<u8, k_session_key_len> key{}; std::array<u8, k_session_key_len> key{};
std::copy(random_host_.begin(), random_host_.end(), random.begin()); std::copy(m_random_host.begin(), m_random_host.end(), random.begin());
std::copy(random_client_.begin(), random_client_.end(), std::copy(m_random_client.begin(), m_random_client.end(),
random.begin() + k_random_len); random.begin() + k_random_len);
prf_sha256(master_secret_, prf_sha256(m_master_secret,
"EXPORTER DAWN data channel session key for controller", random, "EXPORTER DAWN data channel session key for controller", random,
key); key);
if (send_complete()) if (send_complete())
log_msg(log_level::error, "auth: send complete failed"); log_msg(log_level::error, "auth: send complete failed");
if (sink_.set_encryption_key(key)) if (m_sink.set_encryption_key(key))
log_msg(log_level::error, "auth: set encryption key failed"); log_msg(log_level::error, "auth: set encryption key failed");
} }
auto auth::handle_pkt_acknowledge() -> int auto auth::handle_pkt_acknowledge() -> int
{ {
switch (last_sent_command_) { switch (m_last_sent_command) {
case cmd2_host_hello: case cmd2_host_hello:
return request_pkt(cmd2_client_hello, sizeof(pkt2_client_hello)); return request_pkt(cmd2_client_hello, sizeof(pkt2_client_hello));
case cmd2_host_pubkey: case cmd2_host_pubkey:
@@ -358,7 +358,7 @@ auto auth::handle_pkt_data(std::span<u8 const> data) -> int
// The controller upgraded to auth v2: restart the handshake. // The controller upgraded to auth v2: restart the handshake.
if (hdr->handshake.command != hdr->data.command) { if (hdr->handshake.command != hdr->data.command) {
log_msg(log_level::debug, "auth: protocol upgrade to v2"); log_msg(log_level::debug, "auth: protocol upgrade to v2");
transcript_ = sha256{}; m_transcript = sha256{};
return send_hello2(); return send_hello2();
} }
@@ -366,15 +366,15 @@ auto auth::handle_pkt_data(std::span<u8 const> data) -> int
if (err) if (err)
return err; return err;
transcript_.update(data.subspan(sizeof(hdr->handshake))); m_transcript.update(data.subspan(sizeof(hdr->handshake)));
run_deferred_action(); run_deferred_action();
return 0; return 0;
} }
auto auth::run_deferred_action() -> void auto auth::run_deferred_action() -> void
{ {
auto action = deferred_action_; auto action = m_deferred_action;
deferred_action_ = deferred_action::none; m_deferred_action = deferred_action::none;
switch (action) { switch (action) {
case deferred_action::exchange_rsa: case deferred_action::exchange_rsa:
@@ -420,7 +420,7 @@ auto auth::handle_hello(std::span<u8 const> data) -> int
if (data.size() < sizeof(*pkt)) if (data.size() < sizeof(*pkt))
return -EINVAL; return -EINVAL;
std::memcpy(random_client_.data(), pkt->random.data(), k_random_len); std::memcpy(m_random_client.data(), pkt->random.data(), k_random_len);
return request_pkt(cmd_client_certificate, k_certificate_max_len); return request_pkt(cmd_client_certificate, k_certificate_max_len);
} }
@@ -440,8 +440,8 @@ auto auth::handle_certificate(std::span<u8 const> data) -> int
if (i + k_pubkey_len > data.size()) if (i + k_pubkey_len > data.size())
return -EINVAL; return -EINVAL;
std::memcpy(pubkey_client_.data(), data.data() + i, k_pubkey_len); std::memcpy(m_pubkey_client.data(), data.data() + i, k_pubkey_len);
deferred_action_ = deferred_action::exchange_rsa; m_deferred_action = deferred_action::exchange_rsa;
return 0; return 0;
} }
@@ -457,22 +457,22 @@ auto auth::handle_finish(std::span<u8 const> data) -> int
auto transcript = get_transcript(); auto transcript = get_transcript();
std::array<u8, k_transcript_len> finished{}; std::array<u8, k_transcript_len> finished{};
prf_sha256(master_secret_, "Device Finished", transcript, finished); prf_sha256(m_master_secret, "Device Finished", transcript, finished);
if (std::memcmp(pkt->transcript.data(), finished.data(), k_transcript_len)) { if (std::memcmp(pkt->transcript.data(), finished.data(), k_transcript_len)) {
log_msg(log_level::error, "auth: transcript mismatch"); log_msg(log_level::error, "auth: transcript mismatch");
return -EPROTO; return -EPROTO;
} }
deferred_action_ = deferred_action::complete; m_deferred_action = deferred_action::complete;
return 0; return 0;
} }
auto auth::send_hello2() -> int auto auth::send_hello2() -> int
{ {
pkt2_host_hello pkt{}; pkt2_host_hello pkt{};
random_bytes(random_host_); random_bytes(m_random_host);
std::memcpy(pkt.random.data(), random_host_.data(), k_random_len); std::memcpy(pkt.random.data(), m_random_host.data(), k_random_len);
return send_pkt(cmd2_host_hello, &pkt.header, sizeof(pkt)); return send_pkt(cmd2_host_hello, &pkt.header, sizeof(pkt));
} }
@@ -483,7 +483,7 @@ auto auth::handle_hello2(std::span<u8 const> data) -> int
if (data.size() < sizeof(*pkt)) if (data.size() < sizeof(*pkt))
return -EINVAL; return -EINVAL;
std::memcpy(random_client_.data(), pkt->random.data(), k_random_len); std::memcpy(m_random_client.data(), pkt->random.data(), k_random_len);
return request_pkt(cmd2_client_certificate, sizeof(pkt2_client_cert)); return request_pkt(cmd2_client_certificate, sizeof(pkt2_client_cert));
} }
@@ -508,8 +508,8 @@ auto auth::handle_pubkey(std::span<u8 const> data) -> int
if (data.size() < sizeof(*pkt)) if (data.size() < sizeof(*pkt))
return -EINVAL; return -EINVAL;
std::memcpy(pubkey_client2_.data(), pkt->pubkey.data(), k_pubkey2_len); std::memcpy(m_pubkey_client2.data(), pkt->pubkey.data(), k_pubkey2_len);
deferred_action_ = deferred_action::exchange_ecdh; m_deferred_action = deferred_action::exchange_ecdh;
return 0; return 0;
} }
+9 -9
View File
@@ -342,17 +342,17 @@ auto ec_point_is_valid(ec_point const& p) -> bool
// ========================================================================== // ==========================================================================
sha256::sha256() sha256::sha256()
{ {
CC_SHA256_Init(&ctx_); CC_SHA256_Init(&m_ctx);
} }
auto sha256::update(std::span<u8 const> data) -> void auto sha256::update(std::span<u8 const> data) -> void
{ {
CC_SHA256_Update(&ctx_, data.data(), static_cast<CC_LONG>(data.size())); CC_SHA256_Update(&m_ctx, data.data(), static_cast<CC_LONG>(data.size()));
} }
auto sha256::finalize(std::array<u8, k_sha256_len>& out) -> void auto sha256::finalize(std::array<u8, k_sha256_len>& out) -> void
{ {
CC_SHA256_Final(out.data(), &ctx_); CC_SHA256_Final(out.data(), &m_ctx);
} }
// ========================================================================== // ==========================================================================
@@ -375,25 +375,25 @@ hmac_sha256::hmac_sha256(std::span<u8 const> key)
for (int i = 0; i < 64; ++i) { for (int i = 0; i < 64; ++i) {
block[i] = static_cast<u8>(key_block[i] ^ 0x36); block[i] = static_cast<u8>(key_block[i] ^ 0x36);
inner_.update({&block[i], 1}); m_inner.update({&block[i], 1});
} }
for (int i = 0; i < 64; ++i) { for (int i = 0; i < 64; ++i) {
block[i] = static_cast<u8>(key_block[i] ^ 0x5c); block[i] = static_cast<u8>(key_block[i] ^ 0x5c);
outer_.update({&block[i], 1}); m_outer.update({&block[i], 1});
} }
} }
auto hmac_sha256::update(std::span<u8 const> data) -> void auto hmac_sha256::update(std::span<u8 const> data) -> void
{ {
inner_.update(data); m_inner.update(data);
} }
auto hmac_sha256::finalize(std::array<u8, k_sha256_len>& out) -> void auto hmac_sha256::finalize(std::array<u8, k_sha256_len>& out) -> void
{ {
std::array<u8, k_sha256_len> inner_digest{}; std::array<u8, k_sha256_len> inner_digest{};
inner_.finalize(inner_digest); m_inner.finalize(inner_digest);
outer_.update(inner_digest); m_outer.update(inner_digest);
outer_.finalize(out); m_outer.finalize(out);
} }
// ========================================================================== // ==========================================================================
+90 -90
View File
@@ -114,18 +114,18 @@ auto decode_header(gip_header& hdr, u8 const* data, int len) -> int
// client // client
// ========================================================================== // ==========================================================================
client::client(adapter& adapter, u8 id) client::client(adapter& adapter, u8 id)
: adapter_(adapter) : m_adapter(adapter)
, id_(id) , m_id(id)
{ {
} }
auto client::has_interface(xone::guid_t const& guid) const -> bool auto client::has_interface(xone::guid_t const& guid) const -> bool
{ {
if (!interfaces_) if (!m_interfaces)
return false; return false;
for (int i = 0; i < interfaces_->count; ++i) { for (int i = 0; i < m_interfaces->count; ++i) {
if (!std::memcmp(interfaces_->data.data() + i * sizeof(guid), guid.data, if (!std::memcmp(m_interfaces->data.data() + i * sizeof(guid), guid.data,
sizeof(guid))) { sizeof(guid))) {
return true; return true;
} }
@@ -138,46 +138,46 @@ auto client::set_power_mode(u8 mode) -> int
{ {
gip_header hdr{}; gip_header hdr{};
hdr.command = GIP_CMD_POWER; hdr.command = GIP_CMD_POWER;
hdr.options = id_ | GIP_OPT_INTERNAL; hdr.options = m_id | GIP_OPT_INTERNAL;
hdr.packet_length = 1; hdr.packet_length = 1;
return adapter_.send_pkt(*this, hdr, &mode); return m_adapter.send_pkt(*this, hdr, &mode);
} }
auto client::send_rumble(std::span<u8 const> pkt) -> int auto client::send_rumble(std::span<u8 const> pkt) -> int
{ {
gip_header hdr{}; gip_header hdr{};
hdr.command = GIP_CMD_RUMBLE; hdr.command = GIP_CMD_RUMBLE;
hdr.options = id_; hdr.options = m_id;
hdr.packet_length = static_cast<u32>(pkt.size()); hdr.packet_length = static_cast<u32>(pkt.size());
return adapter_.send_pkt(*this, hdr, pkt.data()); return m_adapter.send_pkt(*this, hdr, pkt.data());
} }
auto client::set_led_mode(u8 mode, u8 brightness) -> int auto client::set_led_mode(u8 mode, u8 brightness) -> int
{ {
gip_header hdr{}; gip_header hdr{};
hdr.command = GIP_CMD_LED; hdr.command = GIP_CMD_LED;
hdr.options = id_ | GIP_OPT_INTERNAL; hdr.options = m_id | GIP_OPT_INTERNAL;
hdr.packet_length = 3; hdr.packet_length = 3;
u8 pkt[3] = {0, mode, brightness}; u8 pkt[3] = {0, mode, brightness};
return adapter_.send_pkt(*this, hdr, pkt); return m_adapter.send_pkt(*this, hdr, pkt);
} }
auto client::suggest_audio_format(u8 in, u8 out, bool chat) -> int auto client::suggest_audio_format(u8 in, u8 out, bool chat) -> int
{ {
int err; int err;
if (chat) if (chat)
err = adapter_.set_audio_format_chat(*this, GIP_AUD_FORMAT_CHAT_24KHZ); err = m_adapter.set_audio_format_chat(*this, GIP_AUD_FORMAT_CHAT_24KHZ);
else else
err = adapter_.set_audio_format(*this, in, out); err = m_adapter.set_audio_format(*this, in, out);
if (err) { if (err) {
log_msg(log_level::error, "gip: set audio format failed: %d", err); log_msg(log_level::error, "gip: set audio format failed: %d", err);
return err; return err;
} }
audio_config_in_.format = in; m_audio_config_in.format = in;
audio_config_out_.format = out; m_audio_config_out.format = out;
return 0; return 0;
} }
@@ -185,37 +185,37 @@ auto client::set_audio_volume(u8 in, u8 chat, u8 out) -> int
{ {
gip_header hdr{}; gip_header hdr{};
hdr.command = GIP_CMD_AUDIO_CONTROL; hdr.command = GIP_CMD_AUDIO_CONTROL;
hdr.options = id_ | GIP_OPT_INTERNAL; hdr.options = m_id | GIP_OPT_INTERNAL;
hdr.packet_length = 8; hdr.packet_length = 8;
u8 pkt[8] = {0x03, 0x04, out, chat, in, 0, 0, 0}; u8 pkt[8] = {0x03, 0x04, out, chat, in, 0, 0, 0};
return adapter_.send_pkt(*this, hdr, pkt); return m_adapter.send_pkt(*this, hdr, pkt);
} }
auto client::send_audio_samples(std::span<u8 const> samples) -> int auto client::send_audio_samples(std::span<u8 const> samples) -> int
{ {
// TODO(phase 4): the MT76 transport batches audio packets; send one // TODO(phase 4): the MT76 transport batches audio packets; send one
// frame per packet until the transport exposes an audio buffer API. // frame per packet until the transport exposes an audio buffer API.
auto const& cfg = audio_config_out_; auto const& cfg = m_audio_config_out;
gip_header hdr{}; gip_header hdr{};
hdr.command = GIP_CMD_AUDIO_SAMPLES; hdr.command = GIP_CMD_AUDIO_SAMPLES;
hdr.options = id_ | GIP_OPT_INTERNAL; hdr.options = m_id | GIP_OPT_INTERNAL;
hdr.packet_length = static_cast<u32>(cfg.fragment_size); hdr.packet_length = static_cast<u32>(cfg.fragment_size);
int hdr_len = get_header_length(hdr); int hdr_len = get_header_length(hdr);
for (int i = 0; i < adapter_.audio_packet_count_; ++i) { for (int i = 0; i < m_adapter.m_audio_packet_count; ++i) {
auto const* src = samples.data() + i * cfg.fragment_size; auto const* src = samples.data() + i * cfg.fragment_size;
std::vector<u8> frame(static_cast<std::size_t>(hdr_len) + cfg.fragment_size); std::vector<u8> frame(static_cast<std::size_t>(hdr_len) + cfg.fragment_size);
do { do {
hdr.sequence = adapter_.audio_sequence_++; hdr.sequence = m_adapter.m_audio_sequence++;
} while (!hdr.sequence); } while (!hdr.sequence);
encode_header(hdr, frame.data()); encode_header(hdr, frame.data());
std::memcpy(frame.data() + hdr_len, src, cfg.fragment_size); std::memcpy(frame.data() + hdr_len, src, cfg.fragment_size);
int err = adapter_.transport_.send_frame(frame); int err = m_adapter.m_transport.send_frame(frame);
if (err) if (err)
return err; return err;
} }
@@ -250,18 +250,18 @@ auto client::send(std::span<u8 const> pkt, bool acknowledge) -> int
{ {
gip_header hdr{}; gip_header hdr{};
hdr.command = GIP_CMD_AUTHENTICATE; hdr.command = GIP_CMD_AUTHENTICATE;
hdr.options = id_ | GIP_OPT_INTERNAL; hdr.options = m_id | GIP_OPT_INTERNAL;
hdr.packet_length = static_cast<u32>(pkt.size()); hdr.packet_length = static_cast<u32>(pkt.size());
if (acknowledge) if (acknowledge)
hdr.options |= GIP_OPT_ACKNOWLEDGE; hdr.options |= GIP_OPT_ACKNOWLEDGE;
return adapter_.send_pkt(*this, hdr, pkt.data()); return m_adapter.send_pkt(*this, hdr, pkt.data());
} }
auto client::set_encryption_key(std::span<u8 const> key) -> int auto client::set_encryption_key(std::span<u8 const> key) -> int
{ {
return adapter_.transport_.set_encryption_key(id_, key); return m_adapter.m_transport.set_encryption_key(m_id, key);
} }
// ========================================================================== // ==========================================================================
@@ -269,9 +269,9 @@ auto client::set_encryption_key(std::span<u8 const> key) -> int
// ========================================================================== // ==========================================================================
adapter::adapter(transport& transport, client_listener& listener, adapter::adapter(transport& transport, client_listener& listener,
int audio_packet_count) int audio_packet_count)
: transport_(transport) : m_transport(transport)
, listener_(listener) , m_listener(listener)
, audio_packet_count_(audio_packet_count) , m_audio_packet_count(audio_packet_count)
{ {
} }
@@ -280,7 +280,7 @@ auto adapter::get_client(u8 id) -> client*
if (id >= k_max_clients) if (id >= k_max_clients)
return nullptr; return nullptr;
auto& slot = clients_[id]; auto& slot = m_clients[id];
if (!slot) if (!slot)
slot = std::make_unique<client>(*this, id); slot = std::make_unique<client>(*this, id);
@@ -290,7 +290,7 @@ auto adapter::get_client(u8 id) -> client*
auto adapter::client_count() const -> int auto adapter::client_count() const -> int
{ {
int n = 0; int n = 0;
for (auto const& c : clients_) for (auto const& c : m_clients)
if (c) if (c)
++n; ++n;
return n; return n;
@@ -325,13 +325,13 @@ auto adapter::send_pkt_simple(gip_header& hdr, void const* data) -> int
std::vector<u8> frame(static_cast<std::size_t>(hdr_len) + hdr.packet_length); std::vector<u8> frame(static_cast<std::size_t>(hdr_len) + hdr.packet_length);
while (!hdr.sequence) while (!hdr.sequence)
hdr.sequence = data_sequence_++; hdr.sequence = m_data_sequence++;
encode_header(hdr, frame.data()); encode_header(hdr, frame.data());
if (data && hdr.packet_length) if (data && hdr.packet_length)
std::memcpy(frame.data() + hdr_len, data, hdr.packet_length); std::memcpy(frame.data() + hdr_len, data, hdr.packet_length);
int err = transport_.send_frame(frame); int err = m_transport.send_frame(frame);
if (err) if (err)
log_msg(log_level::debug, "gip: send frame failed: %d", err); log_msg(log_level::debug, "gip: send frame failed: %d", err);
@@ -352,11 +352,11 @@ auto adapter::send_pkt(client& c, gip_header& hdr, void const* data) -> int
if (err) if (err)
return err; return err;
err = init_chunk_buffer(hdr, c.chunk_buf_in_); err = init_chunk_buffer(hdr, c.m_chunk_buf_in);
if (err) if (err)
return err; return err;
std::memcpy(c.chunk_buf_in_->data.data(), data, hdr.chunk_offset); std::memcpy(c.m_chunk_buf_in->data.data(), data, hdr.chunk_offset);
return 0; return 0;
} }
@@ -376,7 +376,7 @@ auto adapter::init_chunk_buffer(gip_header const& hdr,
auto adapter::send_remaining_chunks(client& c) -> int auto adapter::send_remaining_chunks(client& c) -> int
{ {
auto& buf = c.chunk_buf_in_; auto& buf = c.m_chunk_buf_in;
gip_header hdr = buf->header; gip_header hdr = buf->header;
u32 len = buf->length - k_pkt_max_length; u32 len = buf->length - k_pkt_max_length;
@@ -401,24 +401,24 @@ auto adapter::request_identification(client& c) -> int
{ {
gip_header hdr{}; gip_header hdr{};
hdr.command = GIP_CMD_IDENTIFY; hdr.command = GIP_CMD_IDENTIFY;
hdr.options = c.id_ | GIP_OPT_INTERNAL; hdr.options = c.m_id | GIP_OPT_INTERNAL;
return send_pkt(c, hdr, nullptr); return send_pkt(c, hdr, nullptr);
} }
auto adapter::acknowledge_pkt(client& c, gip_header const& ack) -> int auto adapter::acknowledge_pkt(client& c, gip_header const& ack) -> int
{ {
auto& buf = c.chunk_buf_out_; auto& buf = c.m_chunk_buf_out;
gip_header hdr{}; gip_header hdr{};
u8 pkt[9] = {}; u8 pkt[9] = {};
u32 len = ack.chunk_offset + ack.packet_length; u32 len = ack.chunk_offset + ack.packet_length;
hdr.command = GIP_CMD_ACKNOWLEDGE; hdr.command = GIP_CMD_ACKNOWLEDGE;
hdr.options = c.id_ | GIP_OPT_INTERNAL; hdr.options = c.m_id | GIP_OPT_INTERNAL;
hdr.sequence = ack.sequence; hdr.sequence = ack.sequence;
hdr.packet_length = sizeof(pkt); hdr.packet_length = sizeof(pkt);
pkt[1] = ack.command; pkt[1] = ack.command;
pkt[2] = c.id_ | GIP_OPT_INTERNAL; pkt[2] = c.m_id | GIP_OPT_INTERNAL;
store_le16(pkt + 3, static_cast<u16>(len)); store_le16(pkt + 3, static_cast<u16>(len));
if ((ack.options & GIP_OPT_CHUNK) && buf) if ((ack.options & GIP_OPT_CHUNK) && buf)
@@ -429,28 +429,28 @@ auto adapter::acknowledge_pkt(client& c, gip_header const& ack) -> int
auto adapter::remove_client(client& c) -> void auto adapter::remove_client(client& c) -> void
{ {
listener_.on_client_removed(c.id_); m_listener.on_client_removed(c.m_id);
clients_[c.id_].reset(); m_clients[c.m_id].reset();
} }
auto adapter::free_client_info(client& c) -> void auto adapter::free_client_info(client& c) -> void
{ {
c.client_commands_.reset(); c.m_client_commands.reset();
c.firmware_versions_.reset(); c.m_firmware_versions.reset();
c.audio_formats_.reset(); c.m_audio_formats.reset();
c.capabilities_out_.reset(); c.m_capabilities_out.reset();
c.capabilities_in_.reset(); c.m_capabilities_in.reset();
c.classes_.clear(); c.m_classes.clear();
c.interfaces_.reset(); c.m_interfaces.reset();
c.hid_descriptor_.reset(); c.m_hid_descriptor.reset();
} }
auto adapter::add_client(client& c) -> void auto adapter::add_client(client& c) -> void
{ {
log_msg(log_level::info, "gip: client %u identified (vendor 0x%04x, " log_msg(log_level::info, "gip: client %u identified (vendor 0x%04x, "
"product 0x%04x)", "product 0x%04x)",
c.id_, c.hardware_.vendor, c.hardware_.product); c.m_id, c.m_hardware.vendor, c.m_hardware.product);
listener_.on_client_added(c); m_listener.on_client_added(c);
c.start_auth(); c.start_auth();
} }
@@ -475,7 +475,7 @@ auto adapter::make_audio_config(gip_audio_config& cfg) -> int
} }
cfg.buffer_size = cfg.sample_rate * cfg.channels * 2 * k_audio_interval / 1000; cfg.buffer_size = cfg.sample_rate * cfg.channels * 2 * k_audio_interval / 1000;
cfg.fragment_size = cfg.buffer_size / audio_packet_count_; cfg.fragment_size = cfg.buffer_size / m_audio_packet_count;
gip_header hdr{}; gip_header hdr{};
hdr.packet_length = static_cast<u32>(cfg.fragment_size); hdr.packet_length = static_cast<u32>(cfg.fragment_size);
@@ -488,7 +488,7 @@ auto adapter::set_audio_format(client& c, u8 in, u8 out) -> int
{ {
gip_header hdr{}; gip_header hdr{};
hdr.command = GIP_CMD_AUDIO_CONTROL; hdr.command = GIP_CMD_AUDIO_CONTROL;
hdr.options = c.id_ | GIP_OPT_INTERNAL; hdr.options = c.m_id | GIP_OPT_INTERNAL;
hdr.packet_length = 3; hdr.packet_length = 3;
u8 pkt[3] = {0x02, in, out}; u8 pkt[3] = {0x02, in, out};
@@ -499,7 +499,7 @@ auto adapter::set_audio_format_chat(client& c, u8 in_out) -> int
{ {
gip_header hdr{}; gip_header hdr{};
hdr.command = GIP_CMD_AUDIO_CONTROL; hdr.command = GIP_CMD_AUDIO_CONTROL;
hdr.options = c.id_ | GIP_OPT_INTERNAL; hdr.options = c.m_id | GIP_OPT_INTERNAL;
hdr.packet_length = 2; hdr.packet_length = 2;
u8 pkt[2] = {0x01, in_out}; u8 pkt[2] = {0x01, in_out};
@@ -509,7 +509,7 @@ auto adapter::set_audio_format_chat(client& c, u8 in_out) -> int
auto adapter::process_pkt(client& c, gip_header& hdr, void const* data) -> int auto adapter::process_pkt(client& c, gip_header& hdr, void const* data) -> int
{ {
if (hdr.options & GIP_OPT_CHUNK_START) { if (hdr.options & GIP_OPT_CHUNK_START) {
int err = init_chunk_buffer(hdr, c.chunk_buf_out_); int err = init_chunk_buffer(hdr, c.m_chunk_buf_out);
if (err) if (err)
return err; return err;
hdr.chunk_offset = 0; hdr.chunk_offset = 0;
@@ -530,7 +530,7 @@ auto adapter::process_pkt(client& c, gip_header& hdr, void const* data) -> int
auto adapter::process_pkt_chunked(client& c, gip_header const& hdr, auto adapter::process_pkt_chunked(client& c, gip_header const& hdr,
void const* data) -> int void const* data) -> int
{ {
auto& buf = c.chunk_buf_out_; auto& buf = c.m_chunk_buf_out;
if (!buf) { if (!buf) {
// Older gamepads occasionally send spurious completions. // Older gamepads occasionally send spurious completions.
@@ -598,7 +598,7 @@ auto adapter::handle_pkt_acknowledge(client& c, void const* data, u32 len) -> in
return -EINVAL; return -EINVAL;
auto const* p = static_cast<u8 const*>(data); auto const* p = static_cast<u8 const*>(data);
auto& buf = c.chunk_buf_in_; auto& buf = c.m_chunk_buf_in;
if (!buf) if (!buf)
return 0; return 0;
@@ -629,10 +629,10 @@ auto adapter::handle_pkt_announce(client& c, void const* data, u32 len) -> int
u16 fw_major = load_le16(p + 12); u16 fw_major = load_le16(p + 12);
u16 fw_minor = load_le16(p + 14); u16 fw_minor = load_le16(p + 14);
if (!c.hardware_.vendor && !c.hardware_.product && !c.hardware_.version) { if (!c.m_hardware.vendor && !c.m_hardware.product && !c.m_hardware.version) {
c.hardware_.vendor = vendor; c.m_hardware.vendor = vendor;
c.hardware_.product = product; c.m_hardware.product = product;
c.hardware_.version = static_cast<u16>((fw_major << 8) | fw_minor); c.m_hardware.version = static_cast<u16>((fw_major << 8) | fw_minor);
} }
return request_identification(c); return request_identification(c);
@@ -647,12 +647,12 @@ auto adapter::handle_pkt_status(client& c, void const* data, u32 len) -> int
u8 status = p[0]; u8 status = p[0];
if (!(status & 0x80)) { if (!(status & 0x80)) {
log_msg(log_level::debug, "gip: client %u disconnected", c.id_); log_msg(log_level::debug, "gip: client %u disconnected", c.m_id);
remove_client(c); remove_client(c);
return 0; return 0;
} }
listener_.on_battery(c, (status >> 2) & 0x3, status & 0x3); m_listener.on_battery(c, (status >> 2) & 0x3, status & 0x3);
return 0; return 0;
} }
@@ -661,7 +661,7 @@ auto adapter::handle_pkt_identify(client& c, void const* data, u32 len) -> int
if (len < 32) if (len < 32)
return -EINVAL; return -EINVAL;
if (!c.classes_.empty()) { if (!c.m_classes.empty()) {
log_msg(log_level::warn, "gip: client already identified"); log_msg(log_level::warn, "gip: client already identified");
return 0; return 0;
} }
@@ -717,7 +717,7 @@ auto adapter::handle_pkt_virtual_key(client& c, void const* data, u32 len) -> in
if (p[1] != k_vkey_left_win) if (p[1] != k_vkey_left_win)
return -EINVAL; return -EINVAL;
listener_.on_guide_button(c, p[0] != 0); m_listener.on_guide_button(c, p[0] != 0);
return 0; return 0;
} }
@@ -731,41 +731,41 @@ auto adapter::handle_pkt_audio_control(client& c, void const* data, u32 len) ->
case 0x00: // volume chat case 0x00: // volume chat
if (len != 5) if (len != 5)
return -EINVAL; return -EINVAL;
listener_.on_audio_volume(c, p[4], p[3]); m_listener.on_audio_volume(c, p[4], p[3]);
return 0; return 0;
case 0x01: // format chat case 0x01: // format chat
if (len != 2) if (len != 2)
return -EINVAL; return -EINVAL;
if (p[1] != GIP_AUD_FORMAT_CHAT_24KHZ || c.audio_config_in_.buffer_size || if (p[1] != GIP_AUD_FORMAT_CHAT_24KHZ || c.m_audio_config_in.buffer_size ||
c.audio_config_out_.buffer_size) { c.m_audio_config_out.buffer_size) {
return -EPROTO; return -EPROTO;
} }
if (make_audio_config(c.audio_config_in_)) if (make_audio_config(c.m_audio_config_in))
return -EINVAL; return -EINVAL;
if (make_audio_config(c.audio_config_out_)) if (make_audio_config(c.m_audio_config_out))
return -EINVAL; return -EINVAL;
listener_.on_audio_ready(c); m_listener.on_audio_ready(c);
return 0; return 0;
case 0x02: // format case 0x02: // format
if (len != 3) if (len != 3)
return -EINVAL; return -EINVAL;
if (c.audio_config_in_.buffer_size || c.audio_config_out_.buffer_size) if (c.m_audio_config_in.buffer_size || c.m_audio_config_out.buffer_size)
return -EPROTO; return -EPROTO;
if (p[1] != c.audio_config_in_.format || p[2] != c.audio_config_out_.format) { if (p[1] != c.m_audio_config_in.format || p[2] != c.m_audio_config_out.format) {
log_msg(log_level::warn, "gip: audio format rejected: 0x%02x/0x%02x", log_msg(log_level::warn, "gip: audio format rejected: 0x%02x/0x%02x",
c.audio_config_in_.format, c.audio_config_out_.format); c.m_audio_config_in.format, c.m_audio_config_out.format);
return c.suggest_audio_format(p[1], p[2], false); return c.suggest_audio_format(p[1], p[2], false);
} }
if (make_audio_config(c.audio_config_in_)) if (make_audio_config(c.m_audio_config_in))
return -EINVAL; return -EINVAL;
if (make_audio_config(c.audio_config_out_)) if (make_audio_config(c.m_audio_config_out))
return -EINVAL; return -EINVAL;
listener_.on_audio_ready(c); m_listener.on_audio_ready(c);
return 0; return 0;
case 0x03: // volume case 0x03: // volume
if (len != 8) if (len != 8)
return -EINVAL; return -EINVAL;
listener_.on_audio_volume(c, p[4], p[2]); m_listener.on_audio_volume(c, p[4], p[2]);
return 0; return 0;
default: default:
log_msg(log_level::error, "gip: unknown audio subcommand: 0x%02x", p[0]); log_msg(log_level::error, "gip: unknown audio subcommand: 0x%02x", p[0]);
@@ -775,13 +775,13 @@ auto adapter::handle_pkt_audio_control(client& c, void const* data, u32 len) ->
auto adapter::handle_pkt_hid_report(client& c, void const* data, u32 len) -> int auto adapter::handle_pkt_hid_report(client& c, void const* data, u32 len) -> int
{ {
listener_.on_hid_report(c, {static_cast<u8 const*>(data), len}); m_listener.on_hid_report(c, {static_cast<u8 const*>(data), len});
return 0; return 0;
} }
auto adapter::handle_pkt_input(client& c, void const* data, u32 len) -> int auto adapter::handle_pkt_input(client& c, void const* data, u32 len) -> int
{ {
listener_.on_input(c, {static_cast<u8 const*>(data), len}); m_listener.on_input(c, {static_cast<u8 const*>(data), len});
return 0; return 0;
} }
@@ -791,7 +791,7 @@ auto adapter::handle_pkt_audio_samples(client& c, void const* data, u32 len) ->
return -EINVAL; return -EINVAL;
auto const* p = static_cast<u8 const*>(data); auto const* p = static_cast<u8 const*>(data);
listener_.on_audio_samples(c, {p + 2, len - 2}); m_listener.on_audio_samples(c, {p + 2, len - 2});
return 0; return 0;
} }
@@ -831,7 +831,7 @@ auto adapter::parse_client_commands(client& c, u16 const offsets[8],
log_msg(log_level::error, "gip: parse client commands failed: %d", err); log_msg(log_level::error, "gip: parse client commands failed: %d", err);
return err; return err;
} }
c.client_commands_ = std::move(cmds); c.m_client_commands = std::move(cmds);
return 0; return 0;
} }
@@ -844,7 +844,7 @@ auto adapter::parse_firmware_versions(client& c, u16 const offsets[8],
log_msg(log_level::error, "gip: parse firmware versions failed: %d", err); log_msg(log_level::error, "gip: parse firmware versions failed: %d", err);
return err; return err;
} }
c.firmware_versions_ = std::move(vers); c.m_firmware_versions = std::move(vers);
return 0; return 0;
} }
@@ -859,7 +859,7 @@ auto adapter::parse_audio_formats(client& c, u16 const offsets[8],
log_msg(log_level::error, "gip: parse audio formats failed: %d", err); log_msg(log_level::error, "gip: parse audio formats failed: %d", err);
return err; return err;
} }
c.audio_formats_ = std::move(fmts); c.m_audio_formats = std::move(fmts);
return 0; return 0;
} }
@@ -872,14 +872,14 @@ auto adapter::parse_capabilities(client& c, u16 const offsets[8],
log_msg(log_level::error, "gip: parse capabilities out failed: %d", err); log_msg(log_level::error, "gip: parse capabilities out failed: %d", err);
return err; return err;
} }
c.capabilities_out_ = std::move(caps); c.m_capabilities_out = std::move(caps);
err = parse_info_element(data, offsets[4], 1, caps); err = parse_info_element(data, offsets[4], 1, caps);
if (err) { if (err) {
log_msg(log_level::error, "gip: parse capabilities in failed: %d", err); log_msg(log_level::error, "gip: parse capabilities in failed: %d", err);
return err; return err;
} }
c.capabilities_in_ = std::move(caps); c.m_capabilities_in = std::move(caps);
return 0; return 0;
} }
@@ -893,7 +893,7 @@ auto adapter::parse_classes(client& c, std::span<u8 const> data, u16 offset) ->
if (!count) if (!count)
return -EINVAL; return -EINVAL;
while (static_cast<int>(c.classes_.size()) < count) { while (static_cast<int>(c.m_classes.size()) < count) {
if (data.size() < static_cast<std::size_t>(offset) + 2) if (data.size() < static_cast<std::size_t>(offset) + 2)
return -EINVAL; return -EINVAL;
@@ -902,7 +902,7 @@ auto adapter::parse_classes(client& c, std::span<u8 const> data, u16 offset) ->
if (!str_len || data.size() < static_cast<std::size_t>(offset) + str_len) if (!str_len || data.size() < static_cast<std::size_t>(offset) + str_len)
return -EINVAL; return -EINVAL;
c.classes_.emplace_back( c.m_classes.emplace_back(
reinterpret_cast<char const*>(data.data() + offset), str_len); reinterpret_cast<char const*>(data.data() + offset), str_len);
offset += str_len; offset += str_len;
} }
@@ -919,7 +919,7 @@ auto adapter::parse_interfaces(client& c, u16 const offsets[8],
log_msg(log_level::error, "gip: parse interfaces failed: %d", err); log_msg(log_level::error, "gip: parse interfaces failed: %d", err);
return err; return err;
} }
c.interfaces_ = std::move(intfs); c.m_interfaces = std::move(intfs);
return 0; return 0;
} }
@@ -934,7 +934,7 @@ auto adapter::parse_hid_descriptor(client& c, u16 const offsets[8],
log_msg(log_level::error, "gip: parse hid descriptor failed: %d", err); log_msg(log_level::error, "gip: parse hid descriptor failed: %d", err);
return err; return err;
} }
c.hid_descriptor_ = std::move(desc); c.m_hid_descriptor = std::move(desc);
return 0; return 0;
} }
+20 -20
View File
@@ -55,7 +55,7 @@ auto read_firmware_file(char const *path) -> std::optional<std::vector<std::uint
return buf; return buf;
} }
chip::chip(usb::transport &transport) : transport_(transport) {} chip::chip(usb::transport &transport) : m_transport(transport) {}
auto chip::read_register(std::uint32_t addr) -> std::uint32_t auto chip::read_register(std::uint32_t addr) -> std::uint32_t
{ {
@@ -66,7 +66,7 @@ auto chip::read_register(std::uint32_t addr) -> std::uint32_t
} }
std::uint8_t buf[4] = {}; std::uint8_t buf[4] = {};
int ret = transport_.send_vendor_request(req, true, int ret = m_transport.send_vendor_request(req, true,
static_cast<std::uint16_t>(addr >> 16), static_cast<std::uint16_t>(addr >> 16),
static_cast<std::uint16_t>(addr & 0xFFFF), static_cast<std::uint16_t>(addr & 0xFFFF),
buf, sizeof(buf)); buf, sizeof(buf));
@@ -88,7 +88,7 @@ auto chip::write_register(std::uint32_t addr, std::uint32_t val) -> void
std::uint8_t buf[4]; std::uint8_t buf[4];
xone::store_le32(buf, val); xone::store_le32(buf, val);
int ret = transport_.send_vendor_request(req, false, int ret = m_transport.send_vendor_request(req, false,
static_cast<std::uint16_t>(addr >> 16), static_cast<std::uint16_t>(addr >> 16),
static_cast<std::uint16_t>(addr & 0xFFFF), static_cast<std::uint16_t>(addr & 0xFFFF),
buf, sizeof(buf)); buf, sizeof(buf));
@@ -166,13 +166,13 @@ auto chip::send_command(std::uint32_t cmd, void const *payload,
| field_prep(mt_mcu_msg_cmd_type, cmd); | field_prep(mt_mcu_msg_cmd_type, cmd);
auto buf = build_message(info, payload, payload_len); auto buf = build_message(info, payload, payload_len);
auto ret = transport_.bulk_write(buf.data(), buf.size()); auto ret = m_transport.bulk_write(buf.data(), buf.size());
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
auto chip::load_ivb() -> int auto chip::load_ivb() -> int
{ {
return transport_.send_vendor_request(usb::vendor_request::dev_mode, false, return m_transport.send_vendor_request(usb::vendor_request::dev_mode, false,
static_cast<std::uint16_t>(fw_load_ivb), 0, static_cast<std::uint16_t>(fw_load_ivb), 0,
nullptr, 0); nullptr, 0);
} }
@@ -565,17 +565,17 @@ auto chip::switch_channel(channel const *chan) -> int
auto chip::evaluate_channels() -> int auto chip::evaluate_channels() -> int
{ {
for (std::size_t i = 0; i < num_channels; i++) for (std::size_t i = 0; i < num_channels; i++)
channels_[i] = channels[i]; m_channels[i] = channels[i];
for (std::size_t i = 0; i < num_channels; i++) { for (std::size_t i = 0; i < num_channels; i++) {
if (auto err = get_channel_power(&channels_[i]); err != 0) if (auto err = get_channel_power(&m_channels[i]); err != 0)
return err; return err;
if (auto err = switch_channel(&channels_[i]); err != 0) if (auto err = switch_channel(&m_channels[i]); err != 0)
return err; return err;
} }
// The last channel may not be the best one. // The last channel may not be the best one.
current_channel_ = channels_.back(); m_current_channel = m_channels.back();
return 0; return 0;
} }
@@ -591,8 +591,8 @@ auto chip::init_channels() -> int
// Disable promiscuous mode. // Disable promiscuous mode.
write_register(mt_rx_filtr_cfg, 0x017f17); write_register(mt_rx_filtr_cfg, 0x017f17);
current_channel_.scan = true; m_current_channel.scan = true;
if (auto err = switch_channel(&current_channel_); err != 0) if (auto err = switch_channel(&m_current_channel); err != 0)
return err; return err;
if (auto err = set_power_mode(power_mode::radio_off); err != 0) if (auto err = set_power_mode(power_mode::radio_off); err != 0)
@@ -603,8 +603,8 @@ auto chip::init_channels() -> int
if (auto err = set_power_mode(power_mode::radio_on); err != 0) if (auto err = set_power_mode(power_mode::radio_on); err != 0)
return err; return err;
current_channel_.scan = false; m_current_channel.scan = false;
if (auto err = switch_channel(&current_channel_); err != 0) if (auto err = switch_channel(&m_current_channel); err != 0)
return err; return err;
return set_channel_candidates(); return set_channel_candidates();
@@ -667,10 +667,10 @@ auto chip::set_channel_candidates() -> int
}; };
append(1); append(1);
append(current_channel_.index); append(m_current_channel.index);
append(num_channels - 1); append(num_channels - 1);
for (auto const &c : channels_) for (auto const &c : m_channels)
if (c.index != current_channel_.index) if (c.index != m_current_channel.index)
append(c.index); append(c.index);
return send_ms_command(ms_command::ms_set_chan_candidates, buf.data(), return send_ms_command(ms_command::ms_set_chan_candidates, buf.data(),
@@ -728,7 +728,7 @@ auto chip::set_wow_enable(bool enable) -> int
std::uint8_t payload[6]; std::uint8_t payload[6];
xone::store_le32(payload + 0, static_cast<std::uint32_t>(wow_feature::wow_enable)); xone::store_le32(payload + 0, static_cast<std::uint32_t>(wow_feature::wow_enable));
payload[4] = enable ? 1 : 0; payload[4] = enable ? 1 : 0;
payload[5] = current_channel_.index; payload[5] = m_current_channel.index;
return send_command(mcu_cmd::cmd_wow_feature, payload, sizeof(payload)); return send_command(mcu_cmd::cmd_wow_feature, payload, sizeof(payload));
} }
@@ -762,7 +762,7 @@ auto chip::resume_radio() -> int
if (auto err = set_wow_enable(false); err != 0) if (auto err = set_wow_enable(false); err != 0)
return err; return err;
if (auto err = switch_channel(&current_channel_); err != 0) if (auto err = switch_channel(&m_current_channel); err != 0)
return err; return err;
if (auto err = set_pairing(false); err != 0) if (auto err = set_pairing(false); err != 0)
@@ -804,7 +804,7 @@ auto chip::send_wlan(std::span<std::uint8_t const> frame) -> int
| mt_txd_info_80211; | mt_txd_info_80211;
auto buf = build_message(info, payload.data(), payload.size()); auto buf = build_message(info, payload.data(), payload.size());
auto ret = transport_.bulk_write(buf.data(), buf.size()); auto ret = m_transport.bulk_write(buf.data(), buf.size());
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
@@ -847,7 +847,7 @@ auto chip::send_client_frame(std::uint8_t wcid,
| field_prep(mt_mcu_msg_port, dma_msg_port::cpu_tx_port) | field_prep(mt_mcu_msg_port, dma_msg_port::cpu_tx_port)
| field_prep(mt_mcu_msg_cmd_type, 0); | field_prep(mt_mcu_msg_cmd_type, 0);
auto buf = build_message(info, payload.data(), payload.size()); auto buf = build_message(info, payload.data(), payload.size());
auto ret = transport_.bulk_write(buf.data(), buf.size()); auto ret = m_transport.bulk_write(buf.data(), buf.size());
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
+93 -93
View File
@@ -144,28 +144,28 @@ auto transport::probe(frame_callback frames, disconnect_callback disconnected) -
void transport::stop_pump() void transport::stop_pump()
{ {
{ {
std::lock_guard<std::mutex> lock(state_->lock); std::lock_guard<std::mutex> lock(m_state->lock);
if (state_->stopping) if (m_state->stopping)
return; return;
state_->stopping = true; m_state->stopping = true;
} }
for (auto &slot : state_->slots) for (auto &slot : m_state->slots)
(*slot.iface_ref)->AbortPipe(slot.iface_ref, slot.pipe_ref); (*slot.iface_ref)->AbortPipe(slot.iface_ref, slot.pipe_ref);
if (!state_->thread_started) if (!m_state->thread_started)
return; return;
CFRunLoopRef runloop = nullptr; CFRunLoopRef runloop = nullptr;
{ {
std::unique_lock<std::mutex> lock(state_->lock); std::unique_lock<std::mutex> lock(m_state->lock);
state_->cv.wait(lock, [this] { return state_->loop_ready && state_->in_flight == 0; }); m_state->cv.wait(lock, [this] { return m_state->loop_ready && m_state->in_flight == 0; });
runloop = state_->runloop; runloop = m_state->runloop;
} }
// The reader thread is joined below; no callback can run after this. // The reader thread is joined below; no callback can run after this.
CFRunLoopStop(runloop); CFRunLoopStop(runloop);
state_->thread.join(); m_state->thread.join();
} }
auto transport::re_enumerate() -> int auto transport::re_enumerate() -> int
@@ -177,65 +177,65 @@ auto transport::re_enumerate() -> int
// references while the kernel tears them down. // references while the kernel tears them down.
stop_pump(); stop_pump();
auto kr = (*state_->dev_ref)->USBDeviceReEnumerate(state_->dev_ref, kUSBAddExtraResetTimeMask); auto kr = (*m_state->dev_ref)->USBDeviceReEnumerate(m_state->dev_ref, kUSBAddExtraResetTimeMask);
if (kr != kIOReturnSuccess) { if (kr != kIOReturnSuccess) {
xone::log_msg(log_level::error, "usb: re-enumerate failed (%d)", kr); xone::log_msg(log_level::error, "usb: re-enumerate failed (%d)", kr);
return -EIO; return -EIO;
} }
// The kernel terminated all of our clients; the USB references are dead. // The kernel terminated all of our clients; the USB references are dead.
state_->re_enumerated = true; m_state->re_enumerated = true;
xone::log_msg(log_level::info, "usb: re-enumerate ok"); xone::log_msg(log_level::info, "usb: re-enumerate ok");
return 0; return 0;
} }
transport::~transport() transport::~transport()
{ {
if (!state_) if (!m_state)
return; return;
stop_pump(); stop_pump();
// Release the termination watch and async event sources. // Release the termination watch and async event sources.
if (state_->termination_iter) if (m_state->termination_iter)
IOObjectRelease(state_->termination_iter); IOObjectRelease(m_state->termination_iter);
if (state_->notify_port) if (m_state->notify_port)
IONotificationPortDestroy(state_->notify_port); IONotificationPortDestroy(m_state->notify_port);
if (state_->re_enumerated) { if (m_state->re_enumerated) {
// The kernel already tore down the device and interfaces. // The kernel already tore down the device and interfaces.
if (state_->service) if (m_state->service)
IOObjectRelease(state_->service); IOObjectRelease(m_state->service);
return; return;
} }
for (auto *source : state_->sources) for (auto *source : m_state->sources)
CFRelease(source); CFRelease(source);
// Close the interfaces and their endpoint pipes. // Close the interfaces and their endpoint pipes.
for (auto &conn : state_->ifaces) { for (auto &conn : m_state->ifaces) {
(*conn.iface_ref)->USBInterfaceClose(conn.iface_ref); (*conn.iface_ref)->USBInterfaceClose(conn.iface_ref);
(*conn.iface_ref)->Release(conn.iface_ref); (*conn.iface_ref)->Release(conn.iface_ref);
IODestroyPlugInInterface(conn.iodev); IODestroyPlugInInterface(conn.iodev);
} }
// Close the device connection. // Close the device connection.
if (state_->dev_ref) { if (m_state->dev_ref) {
if (state_->dev_opened) if (m_state->dev_opened)
(*state_->dev_ref)->USBDeviceClose(state_->dev_ref); (*m_state->dev_ref)->USBDeviceClose(m_state->dev_ref);
(*state_->dev_ref)->Release(state_->dev_ref); (*m_state->dev_ref)->Release(m_state->dev_ref);
} }
if (state_->dev_iodev) if (m_state->dev_iodev)
IODestroyPlugInInterface(state_->dev_iodev); IODestroyPlugInInterface(m_state->dev_iodev);
if (state_->service) if (m_state->service)
IOObjectRelease(state_->service); IOObjectRelease(m_state->service);
} }
auto transport::open(frame_callback frames, disconnect_callback disconnected) -> bool auto transport::open(frame_callback frames, disconnect_callback disconnected) -> bool
{ {
state_ = std::make_unique<state>(); m_state = std::make_unique<state>();
state_->frames = std::move(frames); m_state->frames = std::move(frames);
state_->disconnected = std::move(disconnected); m_state->disconnected = std::move(disconnected);
// Find the dongle service (class match, filter by VID/PID). // Find the dongle service (class match, filter by VID/PID).
io_iterator_t iter = 0; io_iterator_t iter = 0;
@@ -250,8 +250,8 @@ auto transport::open(frame_callback frames, disconnect_callback disconnected) ->
break; break;
auto vp = read_vid_pid(service); auto vp = read_vid_pid(service);
if (vp && is_dongle(*vp)) { if (vp && is_dongle(*vp)) {
state_->service = service; m_state->service = service;
state_->pid = vp->pid; m_state->pid = vp->pid;
found = true; found = true;
} else { } else {
IOObjectRelease(service); IOObjectRelease(service);
@@ -263,32 +263,32 @@ auto transport::open(frame_callback frames, disconnect_callback disconnected) ->
// Open the device connection. // Open the device connection.
SInt32 score = 0; SInt32 score = 0;
kr = IOCreatePlugInInterfaceForService(state_->service, kIOUSBDeviceUserClientTypeID, kr = IOCreatePlugInInterfaceForService(m_state->service, kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID, &state_->dev_iodev, &score); kIOCFPlugInInterfaceID, &m_state->dev_iodev, &score);
if (kr != kIOReturnSuccess) { if (kr != kIOReturnSuccess) {
xone::log_msg(log_level::error, "usb: create device interface failed (%d)", kr); xone::log_msg(log_level::error, "usb: create device interface failed (%d)", kr);
return false; return false;
} }
void *slot = nullptr; void *slot = nullptr;
HRESULT hr = (*state_->dev_iodev)->QueryInterface(state_->dev_iodev, HRESULT hr = (*m_state->dev_iodev)->QueryInterface(m_state->dev_iodev,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID500), &slot); CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID500), &slot);
if (hr != S_OK || !slot) { if (hr != S_OK || !slot) {
xone::log_msg(log_level::error, "usb: query device interface failed"); xone::log_msg(log_level::error, "usb: query device interface failed");
return false; return false;
} }
state_->dev_ref = static_cast<IOUSBDeviceInterface500 **>(slot); m_state->dev_ref = static_cast<IOUSBDeviceInterface500 **>(slot);
kr = (*state_->dev_ref)->USBDeviceOpen(state_->dev_ref); kr = (*m_state->dev_ref)->USBDeviceOpen(m_state->dev_ref);
if (kr != kIOReturnSuccess) { if (kr != kIOReturnSuccess) {
xone::log_msg(log_level::error, "usb: open device failed (%d)", kr); xone::log_msg(log_level::error, "usb: open device failed (%d)", kr);
return false; return false;
} }
state_->dev_opened = true; m_state->dev_opened = true;
// Reset the chip so it starts from the boot ROM (port of the // Reset the chip so it starts from the boot ROM (port of the
// usb_reset_device call in xone_dongle_probe). // usb_reset_device call in xone_dongle_probe).
kr = (*state_->dev_ref)->ResetDevice(state_->dev_ref); kr = (*m_state->dev_ref)->ResetDevice(m_state->dev_ref);
if (kr != kIOReturnSuccess) { if (kr != kIOReturnSuccess) {
xone::log_msg(log_level::error, "usb: reset device failed (%d)", kr); xone::log_msg(log_level::error, "usb: reset device failed (%d)", kr);
return false; return false;
@@ -296,7 +296,7 @@ auto transport::open(frame_callback frames, disconnect_callback disconnected) ->
// Open every interface and collect the endpoint pipes we need. // Open every interface and collect the endpoint pipes we need.
io_iterator_t children = 0; io_iterator_t children = 0;
kr = IORegistryEntryGetChildIterator(state_->service, kIOServicePlane, &children); kr = IORegistryEntryGetChildIterator(m_state->service, kIOServicePlane, &children);
if (kr != kIOReturnSuccess) if (kr != kIOReturnSuccess)
return false; return false;
@@ -309,57 +309,57 @@ auto transport::open(frame_callback frames, disconnect_callback disconnected) ->
} }
IOObjectRelease(children); IOObjectRelease(children);
if (!state_->in_cmd_pipe || !state_->in_wlan_pipe || !state_->out_pipe) { if (!m_state->in_cmd_pipe || !m_state->in_wlan_pipe || !m_state->out_pipe) {
xone::log_msg(log_level::error, "usb: missing endpoint (cmd in=%d, wlan in=%d, out=%d)", xone::log_msg(log_level::error, "usb: missing endpoint (cmd in=%d, wlan in=%d, out=%d)",
state_->in_cmd_pipe.has_value(), state_->in_wlan_pipe.has_value(), m_state->in_cmd_pipe.has_value(), m_state->in_wlan_pipe.has_value(),
state_->out_pipe.has_value()); m_state->out_pipe.has_value());
return false; return false;
} }
// Async completion dispatch for the opened interfaces. // Async completion dispatch for the opened interfaces.
for (auto &conn : state_->ifaces) { for (auto &conn : m_state->ifaces) {
CFRunLoopSourceRef source = nullptr; CFRunLoopSourceRef source = nullptr;
if ((*conn.iface_ref)->CreateInterfaceAsyncEventSource(conn.iface_ref, &source) if ((*conn.iface_ref)->CreateInterfaceAsyncEventSource(conn.iface_ref, &source)
== kIOReturnSuccess == kIOReturnSuccess
&& source) && source)
state_->sources.push_back(source); m_state->sources.push_back(source);
} }
// Watch for the dongle going away (unplug or chip reconnect). The // Watch for the dongle going away (unplug or chip reconnect). The
// matching dictionary is consumed by this call. // matching dictionary is consumed by this call.
state_->notify_port = IONotificationPortCreate(0); m_state->notify_port = IONotificationPortCreate(0);
kr = IOServiceAddMatchingNotification(state_->notify_port, kIOTerminatedNotification, kr = IOServiceAddMatchingNotification(m_state->notify_port, kIOTerminatedNotification,
IOServiceMatching("IOUSBDevice"), IOServiceMatching("IOUSBDevice"),
on_dongle_terminated, this, on_dongle_terminated, this,
&state_->termination_iter); &m_state->termination_iter);
if (kr != kIOReturnSuccess) { if (kr != kIOReturnSuccess) {
xone::log_msg(log_level::error, "usb: add termination notification failed (%d)", kr); xone::log_msg(log_level::error, "usb: add termination notification failed (%d)", kr);
return false; return false;
} }
state_->thread = std::thread([this] { worker_loop(); }); m_state->thread = std::thread([this] { worker_loop(); });
state_->thread_started = true; m_state->thread_started = true;
// Submit the initial async reads (EP 0x05 IN and EP 0x04 IN). Reserve so // Submit the initial async reads (EP 0x05 IN and EP 0x04 IN). Reserve so
// the slot addresses stay valid for the ReadPipeAsync refcons. // the slot addresses stay valid for the ReadPipeAsync refcons.
state_->slots.reserve(num_in_reads * 2); m_state->slots.reserve(num_in_reads * 2);
auto submit_all = [this](std::optional<state::pipe_ref> const &pipe, auto submit_all = [this](std::optional<state::pipe_ref> const &pipe,
std::uint8_t ep, std::size_t buf_len) -> bool { std::uint8_t ep, std::size_t buf_len) -> bool {
for (std::size_t i = 0; i < num_in_reads; i++) { for (std::size_t i = 0; i < num_in_reads; i++) {
state_->slots.push_back( m_state->slots.push_back(
{ this, ep, pipe->iface_ref, pipe->ref, std::vector<std::uint8_t>(buf_len) }); { this, ep, pipe->iface_ref, pipe->ref, std::vector<std::uint8_t>(buf_len) });
if (!submit_read(&state_->slots.back())) if (!submit_read(&m_state->slots.back()))
return false; return false;
} }
return true; return true;
}; };
if (!submit_all(state_->in_cmd_pipe, ep_in_cmd, len_cmd_pkt)) if (!submit_all(m_state->in_cmd_pipe, ep_in_cmd, len_cmd_pkt))
return false; return false;
if (!submit_all(state_->in_wlan_pipe, ep_in_wlan, len_wlan_pkt)) if (!submit_all(m_state->in_wlan_pipe, ep_in_wlan, len_wlan_pkt))
return false; return false;
xone::log_msg(log_level::info, "usb: dongle connected (pid=0x%04x)", state_->pid); xone::log_msg(log_level::info, "usb: dongle connected (pid=0x%04x)", m_state->pid);
return true; return true;
} }
@@ -387,7 +387,7 @@ auto transport::open_interface(io_service_t child) -> bool
return false; return false;
} }
state_->ifaces.push_back(conn); m_state->ifaces.push_back(conn);
// Scan the interface's pipes for the endpoints we need. // Scan the interface's pipes for the endpoints we need.
UInt8 num_pipes = 0; UInt8 num_pipes = 0;
@@ -403,12 +403,12 @@ auto transport::open_interface(io_service_t child) -> bool
continue; continue;
std::uint8_t ep = static_cast<std::uint8_t>(number); std::uint8_t ep = static_cast<std::uint8_t>(number);
if (direction == kUSBIn && ep == ep_in_cmd && !state_->in_cmd_pipe.has_value()) if (direction == kUSBIn && ep == ep_in_cmd && !m_state->in_cmd_pipe.has_value())
state_->in_cmd_pipe = { conn.iface_ref, i }; m_state->in_cmd_pipe = { conn.iface_ref, i };
else if (direction == kUSBIn && ep == ep_in_wlan && !state_->in_wlan_pipe.has_value()) else if (direction == kUSBIn && ep == ep_in_wlan && !m_state->in_wlan_pipe.has_value())
state_->in_wlan_pipe = { conn.iface_ref, i }; m_state->in_wlan_pipe = { conn.iface_ref, i };
else if (direction == kUSBOut && ep == ep_out && !state_->out_pipe.has_value()) else if (direction == kUSBOut && ep == ep_out && !m_state->out_pipe.has_value())
state_->out_pipe = { conn.iface_ref, i }; m_state->out_pipe = { conn.iface_ref, i };
} }
return true; return true;
@@ -416,7 +416,7 @@ auto transport::open_interface(io_service_t child) -> bool
auto transport::pid() const -> std::uint16_t auto transport::pid() const -> std::uint16_t
{ {
return state_->pid; return m_state->pid;
} }
auto transport::send_vendor_request(vendor_request req, bool is_read, std::uint16_t w_value, auto transport::send_vendor_request(vendor_request req, bool is_read, std::uint16_t w_value,
@@ -432,7 +432,7 @@ auto transport::send_vendor_request(vendor_request req, bool is_read, std::uint1
request.wLength = static_cast<UInt16>(len); request.wLength = static_cast<UInt16>(len);
request.pData = data; request.pData = data;
IOReturn ret = (*state_->dev_ref)->DeviceRequest(state_->dev_ref, &request); IOReturn ret = (*m_state->dev_ref)->DeviceRequest(m_state->dev_ref, &request);
if (ret != kIOReturnSuccess || request.wLenDone != len) { if (ret != kIOReturnSuccess || request.wLenDone != len) {
xone::log_msg(log_level::error, "usb: vendor request 0x%02x failed (%d)", xone::log_msg(log_level::error, "usb: vendor request 0x%02x failed (%d)",
static_cast<int>(req), ret); static_cast<int>(req), ret);
@@ -444,7 +444,7 @@ auto transport::send_vendor_request(vendor_request req, bool is_read, std::uint1
auto transport::bulk_write(void const *data, std::size_t len) -> int auto transport::bulk_write(void const *data, std::size_t len) -> int
{ {
auto &pipe = state_->out_pipe.value(); auto &pipe = m_state->out_pipe.value();
IOReturn ret = (*pipe.iface_ref)->WritePipe(pipe.iface_ref, pipe.ref, IOReturn ret = (*pipe.iface_ref)->WritePipe(pipe.iface_ref, pipe.ref,
const_cast<void *>(data), static_cast<UInt32>(len)); const_cast<void *>(data), static_cast<UInt32>(len));
if (ret != kIOReturnSuccess) { if (ret != kIOReturnSuccess) {
@@ -458,19 +458,19 @@ auto transport::bulk_write(void const *data, std::size_t len) -> int
auto transport::submit_read(read_slot *slot) -> bool auto transport::submit_read(read_slot *slot) -> bool
{ {
{ {
std::lock_guard<std::mutex> lock(state_->lock); std::lock_guard<std::mutex> lock(m_state->lock);
if (state_->stopping) if (m_state->stopping)
return false; return false;
state_->in_flight++; m_state->in_flight++;
} }
IOReturn ret = (*slot->iface_ref)->ReadPipeAsync(slot->iface_ref, slot->pipe_ref, IOReturn ret = (*slot->iface_ref)->ReadPipeAsync(slot->iface_ref, slot->pipe_ref,
slot->buf.data(), static_cast<UInt32>(slot->buf.size()), slot->buf.data(), static_cast<UInt32>(slot->buf.size()),
on_read_completion, slot); on_read_completion, slot);
if (ret != kIOReturnSuccess) { if (ret != kIOReturnSuccess) {
std::lock_guard<std::mutex> lock(state_->lock); std::lock_guard<std::mutex> lock(m_state->lock);
state_->in_flight--; m_state->in_flight--;
state_->cv.notify_all(); m_state->cv.notify_all();
return false; return false;
} }
@@ -480,16 +480,16 @@ auto transport::submit_read(read_slot *slot) -> bool
void transport::worker_loop() void transport::worker_loop()
{ {
CFRunLoopRef runloop = CFRunLoopGetCurrent(); CFRunLoopRef runloop = CFRunLoopGetCurrent();
for (auto *source : state_->sources) for (auto *source : m_state->sources)
CFRunLoopAddSource(runloop, source, kCFRunLoopDefaultMode); CFRunLoopAddSource(runloop, source, kCFRunLoopDefaultMode);
CFRunLoopAddSource(runloop, IONotificationPortGetRunLoopSource(state_->notify_port), CFRunLoopAddSource(runloop, IONotificationPortGetRunLoopSource(m_state->notify_port),
kCFRunLoopDefaultMode); kCFRunLoopDefaultMode);
{ {
std::lock_guard<std::mutex> lock(state_->lock); std::lock_guard<std::mutex> lock(m_state->lock);
state_->runloop = runloop; m_state->runloop = runloop;
state_->loop_ready = true; m_state->loop_ready = true;
state_->cv.notify_all(); m_state->cv.notify_all();
} }
CFRunLoopRun(); CFRunLoopRun();
@@ -497,13 +497,13 @@ void transport::worker_loop()
void transport::handle_read(read_slot *slot, IOReturn result, std::size_t len) void transport::handle_read(read_slot *slot, IOReturn result, std::size_t len)
{ {
if (result == kIOReturnSuccess && len > 0 && state_->frames) if (result == kIOReturnSuccess && len > 0 && m_state->frames)
state_->frames(slot->ep, slot->buf.data(), len); m_state->frames(slot->ep, slot->buf.data(), len);
std::lock_guard<std::mutex> lock(state_->lock); std::lock_guard<std::mutex> lock(m_state->lock);
if (state_->stopping) { if (m_state->stopping) {
state_->in_flight--; m_state->in_flight--;
state_->cv.notify_all(); m_state->cv.notify_all();
return; return;
} }
@@ -511,8 +511,8 @@ void transport::handle_read(read_slot *slot, IOReturn result, std::size_t len)
slot->buf.data(), static_cast<UInt32>(slot->buf.size()), slot->buf.data(), static_cast<UInt32>(slot->buf.size()),
on_read_completion, slot); on_read_completion, slot);
if (ret != kIOReturnSuccess) { if (ret != kIOReturnSuccess) {
state_->in_flight--; m_state->in_flight--;
state_->cv.notify_all(); m_state->cv.notify_all();
} }
} }
@@ -520,11 +520,11 @@ void transport::handle_disconnected()
{ {
disconnect_callback callback; disconnect_callback callback;
{ {
std::lock_guard<std::mutex> lock(state_->lock); std::lock_guard<std::mutex> lock(m_state->lock);
if (state_->stopping || state_->disconnected_notified) if (m_state->stopping || m_state->disconnected_notified)
return; return;
state_->disconnected_notified = true; m_state->disconnected_notified = true;
callback = state_->disconnected; callback = m_state->disconnected;
} }
xone::log_msg(log_level::info, "usb: dongle disconnected"); xone::log_msg(log_level::info, "usb: dongle disconnected");
@@ -549,7 +549,7 @@ void transport::on_dongle_terminated(void *refcon, io_iterator_t iter)
if (!service) if (!service)
break; break;
auto vp = read_vid_pid(service); auto vp = read_vid_pid(service);
if (vp && vp->vid == vid && vp->pid == t->state_->pid) if (vp && vp->vid == vid && vp->pid == t->m_state->pid)
ours = true; ours = true;
IOObjectRelease(service); IOObjectRelease(service);
} }