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:
+1
-1
@@ -6,7 +6,7 @@ if(NOT CMAKE_GENERATOR MATCHES "^(Ninja|Xcode)$")
|
||||
endif()
|
||||
|
||||
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)
|
||||
|
||||
|
||||
@@ -79,15 +79,15 @@ private:
|
||||
auto handle_pubkey(std::span<u8 const> data) -> int;
|
||||
auto get_transcript() -> std::array<u8, k_transcript_len>;
|
||||
|
||||
auth_sink& sink_;
|
||||
sha256 transcript_;
|
||||
u8 last_sent_command_ = 0;
|
||||
auth_sink& m_sink;
|
||||
sha256 m_transcript;
|
||||
u8 m_last_sent_command = 0;
|
||||
|
||||
std::array<u8, k_random_len> random_host_{};
|
||||
std::array<u8, k_random_len> random_client_{};
|
||||
std::array<u8, k_pubkey_len> pubkey_client_{};
|
||||
std::array<u8, k_pubkey2_len> pubkey_client2_{};
|
||||
std::array<u8, k_secret_len> master_secret_{};
|
||||
std::array<u8, k_random_len> m_random_host{};
|
||||
std::array<u8, k_random_len> m_random_client{};
|
||||
std::array<u8, k_pubkey_len> m_pubkey_client{};
|
||||
std::array<u8, k_pubkey2_len> m_pubkey_client2{};
|
||||
std::array<u8, k_secret_len> m_master_secret{};
|
||||
|
||||
enum class deferred_action {
|
||||
none,
|
||||
@@ -95,7 +95,7 @@ private:
|
||||
exchange_ecdh,
|
||||
complete,
|
||||
};
|
||||
deferred_action deferred_action_ = deferred_action::none;
|
||||
deferred_action m_deferred_action = deferred_action::none;
|
||||
};
|
||||
|
||||
} // namespace xone::auth
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
auto finalize(std::array<u8, k_sha256_len>& out) -> void;
|
||||
|
||||
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;
|
||||
|
||||
private:
|
||||
sha256 inner_;
|
||||
sha256 outer_;
|
||||
sha256 m_inner;
|
||||
sha256 m_outer;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
+29
-29
@@ -164,11 +164,11 @@ class client : public xone::auth::auth_sink {
|
||||
public:
|
||||
client(adapter& adapter, u8 id);
|
||||
|
||||
auto id() const -> u8 { return id_; }
|
||||
auto hardware() const -> gip_hardware const& { return hardware_; }
|
||||
auto audio_config_in() const -> gip_audio_config const& { return audio_config_in_; }
|
||||
auto audio_config_out() const -> gip_audio_config const& { return audio_config_out_; }
|
||||
auto classes() const -> std::vector<std::string> const& { return classes_; }
|
||||
auto id() const -> u8 { return m_id; }
|
||||
auto hardware() const -> gip_hardware const& { return m_hardware; }
|
||||
auto audio_config_in() const -> gip_audio_config const& { return m_audio_config_in; }
|
||||
auto audio_config_out() const -> gip_audio_config const& { return m_audio_config_out; }
|
||||
auto classes() const -> std::vector<std::string> const& { return m_classes; }
|
||||
|
||||
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 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
|
||||
{
|
||||
return auth_.process_pkt(data);
|
||||
return m_auth.process_pkt(data);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class adapter;
|
||||
|
||||
adapter& adapter_;
|
||||
u8 id_;
|
||||
gip_hardware hardware_{};
|
||||
adapter& m_adapter;
|
||||
u8 m_id;
|
||||
gip_hardware m_hardware{};
|
||||
|
||||
struct info_element {
|
||||
u8 count = 0;
|
||||
std::vector<u8> data;
|
||||
};
|
||||
|
||||
std::unique_ptr<info_element> client_commands_;
|
||||
std::unique_ptr<info_element> firmware_versions_;
|
||||
std::unique_ptr<info_element> audio_formats_;
|
||||
std::unique_ptr<info_element> capabilities_out_;
|
||||
std::unique_ptr<info_element> capabilities_in_;
|
||||
std::vector<std::string> classes_;
|
||||
std::unique_ptr<info_element> interfaces_;
|
||||
std::unique_ptr<info_element> hid_descriptor_;
|
||||
std::unique_ptr<info_element> m_client_commands;
|
||||
std::unique_ptr<info_element> m_firmware_versions;
|
||||
std::unique_ptr<info_element> m_audio_formats;
|
||||
std::unique_ptr<info_element> m_capabilities_out;
|
||||
std::unique_ptr<info_element> m_capabilities_in;
|
||||
std::vector<std::string> m_classes;
|
||||
std::unique_ptr<info_element> m_interfaces;
|
||||
std::unique_ptr<info_element> m_hid_descriptor;
|
||||
|
||||
gip_audio_config audio_config_in_;
|
||||
gip_audio_config audio_config_out_;
|
||||
gip_audio_config m_audio_config_in;
|
||||
gip_audio_config m_audio_config_out;
|
||||
|
||||
// Chunk reassembly buffers (large packets are split into chunks).
|
||||
struct chunk_buffer {
|
||||
@@ -223,10 +223,10 @@ private:
|
||||
u32 length = 0;
|
||||
std::vector<u8> data;
|
||||
};
|
||||
std::unique_ptr<chunk_buffer> chunk_buf_out_;
|
||||
std::unique_ptr<chunk_buffer> chunk_buf_in_;
|
||||
std::unique_ptr<chunk_buffer> m_chunk_buf_out;
|
||||
std::unique_ptr<chunk_buffer> m_chunk_buf_in;
|
||||
|
||||
xone::auth::auth auth_{*this};
|
||||
xone::auth::auth m_auth{*this};
|
||||
};
|
||||
|
||||
class adapter {
|
||||
@@ -288,13 +288,13 @@ private:
|
||||
auto parse_hid_descriptor(client& c, u16 const offsets[8],
|
||||
std::span<u8 const> data) -> int;
|
||||
|
||||
transport& transport_;
|
||||
client_listener& listener_;
|
||||
int audio_packet_count_;
|
||||
transport& m_transport;
|
||||
client_listener& m_listener;
|
||||
int m_audio_packet_count;
|
||||
|
||||
std::array<std::unique_ptr<client>, k_max_clients> clients_;
|
||||
u8 data_sequence_ = 0;
|
||||
u8 audio_sequence_ = 0;
|
||||
std::array<std::unique_ptr<client>, k_max_clients> m_clients;
|
||||
u8 m_data_sequence = 0;
|
||||
u8 m_audio_sequence = 0;
|
||||
};
|
||||
|
||||
} // namespace xone::gip
|
||||
|
||||
@@ -137,10 +137,10 @@ private:
|
||||
auto write_beacon(bool pair) -> int;
|
||||
auto set_channel_candidates() -> int;
|
||||
|
||||
usb::transport &transport_;
|
||||
usb::transport &m_transport;
|
||||
char build_time_[17] = {};
|
||||
std::array<channel, num_channels> channels_{};
|
||||
channel current_channel_{};
|
||||
std::array<channel, num_channels> m_channels{};
|
||||
channel m_current_channel{};
|
||||
};
|
||||
|
||||
} // namespace xone::mt76
|
||||
|
||||
@@ -125,7 +125,7 @@ private:
|
||||
static void on_read_completion(void *refcon, std::int32_t result, void *arg0);
|
||||
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).
|
||||
|
||||
+34
-34
@@ -30,29 +30,29 @@ class controller_transport : public xone::gip::transport {
|
||||
public:
|
||||
controller_transport(xone::mt76::chip& chip, std::uint8_t wcid,
|
||||
std::array<std::uint8_t, 6> mac)
|
||||
: chip_(chip)
|
||||
, wcid_(wcid)
|
||||
, mac_(mac)
|
||||
: m_chip(chip)
|
||||
, m_wcid(wcid)
|
||||
, m_mac(mac)
|
||||
{
|
||||
}
|
||||
|
||||
auto send_frame(std::span<std::uint8_t const> frame) -> int override;
|
||||
auto set_encryption_key(std::uint8_t client_id,
|
||||
std::span<std::uint8_t const> key) -> int override;
|
||||
auto enable_encryption() -> void { encrypted_ = true; }
|
||||
auto enable_encryption() -> void { m_encrypted = true; }
|
||||
|
||||
private:
|
||||
xone::mt76::chip& chip_;
|
||||
std::uint8_t wcid_;
|
||||
std::array<std::uint8_t, 6> mac_;
|
||||
bool encrypted_ = false;
|
||||
xone::mt76::chip& m_chip;
|
||||
std::uint8_t m_wcid;
|
||||
std::array<std::uint8_t, 6> m_mac;
|
||||
bool m_encrypted = false;
|
||||
};
|
||||
|
||||
class controller_listener : public xone::gip::client_listener {
|
||||
public:
|
||||
controller_listener(xone_dongle& dongle, controller& controller)
|
||||
: dongle_(dongle)
|
||||
, controller_(controller)
|
||||
: m_dongle(dongle)
|
||||
, m_controller(controller)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -63,8 +63,8 @@ public:
|
||||
-> void override;
|
||||
|
||||
private:
|
||||
xone_dongle& dongle_;
|
||||
controller& controller_;
|
||||
xone_dongle& m_dongle;
|
||||
controller& m_controller;
|
||||
};
|
||||
|
||||
// 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)
|
||||
-> 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(
|
||||
std::uint8_t client_id, std::span<std::uint8_t const> key) -> int
|
||||
{
|
||||
(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
|
||||
@@ -181,24 +181,24 @@ auto controller_listener::on_client_added(xone::gip::client& client) -> void
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> guard(dongle_.lock);
|
||||
controller_.gip_ready = true;
|
||||
std::lock_guard<std::mutex> guard(m_dongle.lock);
|
||||
m_controller.gip_ready = true;
|
||||
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
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(dongle_.lock);
|
||||
controller_.gip_ready = false;
|
||||
controller_.input_active = false;
|
||||
std::lock_guard<std::mutex> guard(m_dongle.lock);
|
||||
m_controller.gip_ready = false;
|
||||
m_controller.input_active = false;
|
||||
}
|
||||
|
||||
auto controller_listener::on_guide_button(xone::gip::client&, bool down)
|
||||
-> void
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(dongle_.lock);
|
||||
controller_.guide_down = down;
|
||||
std::lock_guard<std::mutex> guard(m_dongle.lock);
|
||||
m_controller.guide_down = down;
|
||||
}
|
||||
|
||||
auto controller_listener::on_input(
|
||||
@@ -208,24 +208,24 @@ auto controller_listener::on_input(
|
||||
if (data.size() < 14)
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> guard(dongle_.lock);
|
||||
controller_.buttons = xone::load_le16(data.data());
|
||||
controller_.trigger_left = xone::load_le16(data.data() + 2);
|
||||
controller_.trigger_right = xone::load_le16(data.data() + 4);
|
||||
controller_.stick_left_x = static_cast<std::int16_t>(
|
||||
std::lock_guard<std::mutex> guard(m_dongle.lock);
|
||||
m_controller.buttons = xone::load_le16(data.data());
|
||||
m_controller.trigger_left = xone::load_le16(data.data() + 2);
|
||||
m_controller.trigger_right = xone::load_le16(data.data() + 4);
|
||||
m_controller.stick_left_x = static_cast<std::int16_t>(
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
++controller_.input_sequence;
|
||||
controller_.input_active = true;
|
||||
++m_controller.input_sequence;
|
||||
m_controller.input_active = true;
|
||||
xone::log_msg(xone::log_level::debug,
|
||||
"api: input wcid=%d buttons=0x%04x lt=%d rt=%d",
|
||||
controller_.wcid, controller_.buttons,
|
||||
controller_.trigger_left, controller_.trigger_right);
|
||||
m_controller.wcid, m_controller.buttons,
|
||||
m_controller.trigger_left, m_controller.trigger_right);
|
||||
}
|
||||
|
||||
auto xone_dongle::setup_controller(controller& c) -> void
|
||||
|
||||
+37
-37
@@ -141,7 +141,7 @@ struct pkt2_client_pubkey {
|
||||
} // namespace
|
||||
|
||||
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;
|
||||
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,
|
||||
"auth: tx command=0x%02x data_length=%u acknowledge=1",
|
||||
cmd, data_len);
|
||||
transcript_.update(
|
||||
m_transcript.update(
|
||||
{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
|
||||
@@ -216,14 +216,14 @@ auto auth::request_pkt(u8 cmd, std::uint16_t len) -> int
|
||||
log_msg(log_level::debug,
|
||||
"auth: tx request command=0x%02x data_length=%u acknowledge=1",
|
||||
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
|
||||
{
|
||||
pkt_host_hello pkt{};
|
||||
random_bytes(random_host_);
|
||||
std::memcpy(pkt.random.data(), random_host_.data(), k_random_len);
|
||||
random_bytes(m_random_host);
|
||||
std::memcpy(pkt.random.data(), m_random_host.data(), k_random_len);
|
||||
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{};
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -240,12 +240,12 @@ auto auth::send_complete() -> int
|
||||
header_control hdr{};
|
||||
hdr.context = ctx_control;
|
||||
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>
|
||||
{
|
||||
sha256 snap = transcript_;
|
||||
sha256 snap = m_transcript;
|
||||
std::array<u8, k_transcript_len> out{};
|
||||
snap.finalize(out);
|
||||
return out;
|
||||
@@ -257,20 +257,20 @@ auto auth::exchange_rsa() -> void
|
||||
std::array<u8, k_random_len * 2> random{};
|
||||
std::array<u8, k_secret_len> pms{};
|
||||
|
||||
std::copy(random_host_.begin(), random_host_.end(), random.begin());
|
||||
std::copy(random_client_.begin(), random_client_.end(),
|
||||
std::copy(m_random_host.begin(), m_random_host.end(), random.begin());
|
||||
std::copy(m_random_client.begin(), m_random_client.end(),
|
||||
random.begin() + k_random_len);
|
||||
|
||||
random_bytes(pms);
|
||||
|
||||
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");
|
||||
return;
|
||||
}
|
||||
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)))
|
||||
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_secret2_len> secret{};
|
||||
|
||||
std::copy(random_host_.begin(), random_host_.end(), random.begin());
|
||||
std::copy(random_client_.begin(), random_client_.end(),
|
||||
std::copy(m_random_host.begin(), m_random_host.end(), random.begin());
|
||||
std::copy(m_random_client.begin(), m_random_client.end(),
|
||||
random.begin() + k_random_len);
|
||||
|
||||
ec_scalar d{};
|
||||
@@ -292,7 +292,7 @@ auto auth::exchange_ecdh() -> void
|
||||
std::memcpy(pkt.pubkey.data(), q.data(), k_pubkey2_len);
|
||||
|
||||
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");
|
||||
return;
|
||||
}
|
||||
@@ -302,7 +302,7 @@ auto auth::exchange_ecdh() -> void
|
||||
h.update(shared_x);
|
||||
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)))
|
||||
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_session_key_len> key{};
|
||||
|
||||
std::copy(random_host_.begin(), random_host_.end(), random.begin());
|
||||
std::copy(random_client_.begin(), random_client_.end(),
|
||||
std::copy(m_random_host.begin(), m_random_host.end(), random.begin());
|
||||
std::copy(m_random_client.begin(), m_random_client.end(),
|
||||
random.begin() + k_random_len);
|
||||
|
||||
prf_sha256(master_secret_,
|
||||
prf_sha256(m_master_secret,
|
||||
"EXPORTER DAWN data channel session key for controller", random,
|
||||
key);
|
||||
|
||||
if (send_complete())
|
||||
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");
|
||||
}
|
||||
|
||||
auto auth::handle_pkt_acknowledge() -> int
|
||||
{
|
||||
switch (last_sent_command_) {
|
||||
switch (m_last_sent_command) {
|
||||
case cmd2_host_hello:
|
||||
return request_pkt(cmd2_client_hello, sizeof(pkt2_client_hello));
|
||||
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.
|
||||
if (hdr->handshake.command != hdr->data.command) {
|
||||
log_msg(log_level::debug, "auth: protocol upgrade to v2");
|
||||
transcript_ = sha256{};
|
||||
m_transcript = sha256{};
|
||||
return send_hello2();
|
||||
}
|
||||
|
||||
@@ -366,15 +366,15 @@ auto auth::handle_pkt_data(std::span<u8 const> data) -> int
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
transcript_.update(data.subspan(sizeof(hdr->handshake)));
|
||||
m_transcript.update(data.subspan(sizeof(hdr->handshake)));
|
||||
run_deferred_action();
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto auth::run_deferred_action() -> void
|
||||
{
|
||||
auto action = deferred_action_;
|
||||
deferred_action_ = deferred_action::none;
|
||||
auto action = m_deferred_action;
|
||||
m_deferred_action = deferred_action::none;
|
||||
|
||||
switch (action) {
|
||||
case deferred_action::exchange_rsa:
|
||||
@@ -420,7 +420,7 @@ auto auth::handle_hello(std::span<u8 const> data) -> int
|
||||
if (data.size() < sizeof(*pkt))
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -440,8 +440,8 @@ auto auth::handle_certificate(std::span<u8 const> data) -> int
|
||||
if (i + k_pubkey_len > data.size())
|
||||
return -EINVAL;
|
||||
|
||||
std::memcpy(pubkey_client_.data(), data.data() + i, k_pubkey_len);
|
||||
deferred_action_ = deferred_action::exchange_rsa;
|
||||
std::memcpy(m_pubkey_client.data(), data.data() + i, k_pubkey_len);
|
||||
m_deferred_action = deferred_action::exchange_rsa;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -457,22 +457,22 @@ auto auth::handle_finish(std::span<u8 const> data) -> int
|
||||
|
||||
auto transcript = get_transcript();
|
||||
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)) {
|
||||
log_msg(log_level::error, "auth: transcript mismatch");
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
deferred_action_ = deferred_action::complete;
|
||||
m_deferred_action = deferred_action::complete;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto auth::send_hello2() -> int
|
||||
{
|
||||
pkt2_host_hello pkt{};
|
||||
random_bytes(random_host_);
|
||||
std::memcpy(pkt.random.data(), random_host_.data(), k_random_len);
|
||||
random_bytes(m_random_host);
|
||||
std::memcpy(pkt.random.data(), m_random_host.data(), k_random_len);
|
||||
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))
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -508,8 +508,8 @@ auto auth::handle_pubkey(std::span<u8 const> data) -> int
|
||||
if (data.size() < sizeof(*pkt))
|
||||
return -EINVAL;
|
||||
|
||||
std::memcpy(pubkey_client2_.data(), pkt->pubkey.data(), k_pubkey2_len);
|
||||
deferred_action_ = deferred_action::exchange_ecdh;
|
||||
std::memcpy(m_pubkey_client2.data(), pkt->pubkey.data(), k_pubkey2_len);
|
||||
m_deferred_action = deferred_action::exchange_ecdh;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+9
-9
@@ -342,17 +342,17 @@ auto ec_point_is_valid(ec_point const& p) -> bool
|
||||
// ==========================================================================
|
||||
sha256::sha256()
|
||||
{
|
||||
CC_SHA256_Init(&ctx_);
|
||||
CC_SHA256_Init(&m_ctx);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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) {
|
||||
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) {
|
||||
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
|
||||
{
|
||||
inner_.update(data);
|
||||
m_inner.update(data);
|
||||
}
|
||||
|
||||
auto hmac_sha256::finalize(std::array<u8, k_sha256_len>& out) -> void
|
||||
{
|
||||
std::array<u8, k_sha256_len> inner_digest{};
|
||||
inner_.finalize(inner_digest);
|
||||
outer_.update(inner_digest);
|
||||
outer_.finalize(out);
|
||||
m_inner.finalize(inner_digest);
|
||||
m_outer.update(inner_digest);
|
||||
m_outer.finalize(out);
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
+90
-90
@@ -114,18 +114,18 @@ auto decode_header(gip_header& hdr, u8 const* data, int len) -> int
|
||||
// client
|
||||
// ==========================================================================
|
||||
client::client(adapter& adapter, u8 id)
|
||||
: adapter_(adapter)
|
||||
, id_(id)
|
||||
: m_adapter(adapter)
|
||||
, m_id(id)
|
||||
{
|
||||
}
|
||||
|
||||
auto client::has_interface(xone::guid_t const& guid) const -> bool
|
||||
{
|
||||
if (!interfaces_)
|
||||
if (!m_interfaces)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < interfaces_->count; ++i) {
|
||||
if (!std::memcmp(interfaces_->data.data() + i * sizeof(guid), guid.data,
|
||||
for (int i = 0; i < m_interfaces->count; ++i) {
|
||||
if (!std::memcmp(m_interfaces->data.data() + i * sizeof(guid), guid.data,
|
||||
sizeof(guid))) {
|
||||
return true;
|
||||
}
|
||||
@@ -138,46 +138,46 @@ auto client::set_power_mode(u8 mode) -> int
|
||||
{
|
||||
gip_header hdr{};
|
||||
hdr.command = GIP_CMD_POWER;
|
||||
hdr.options = id_ | GIP_OPT_INTERNAL;
|
||||
hdr.options = m_id | GIP_OPT_INTERNAL;
|
||||
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
|
||||
{
|
||||
gip_header hdr{};
|
||||
hdr.command = GIP_CMD_RUMBLE;
|
||||
hdr.options = id_;
|
||||
hdr.options = m_id;
|
||||
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
|
||||
{
|
||||
gip_header hdr{};
|
||||
hdr.command = GIP_CMD_LED;
|
||||
hdr.options = id_ | GIP_OPT_INTERNAL;
|
||||
hdr.options = m_id | GIP_OPT_INTERNAL;
|
||||
hdr.packet_length = 3;
|
||||
|
||||
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
|
||||
{
|
||||
int err;
|
||||
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
|
||||
err = adapter_.set_audio_format(*this, in, out);
|
||||
err = m_adapter.set_audio_format(*this, in, out);
|
||||
|
||||
if (err) {
|
||||
log_msg(log_level::error, "gip: set audio format failed: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
audio_config_in_.format = in;
|
||||
audio_config_out_.format = out;
|
||||
m_audio_config_in.format = in;
|
||||
m_audio_config_out.format = out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -185,37 +185,37 @@ auto client::set_audio_volume(u8 in, u8 chat, u8 out) -> int
|
||||
{
|
||||
gip_header hdr{};
|
||||
hdr.command = GIP_CMD_AUDIO_CONTROL;
|
||||
hdr.options = id_ | GIP_OPT_INTERNAL;
|
||||
hdr.options = m_id | GIP_OPT_INTERNAL;
|
||||
hdr.packet_length = 8;
|
||||
|
||||
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
|
||||
{
|
||||
// TODO(phase 4): the MT76 transport batches audio packets; send one
|
||||
// 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{};
|
||||
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);
|
||||
|
||||
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;
|
||||
std::vector<u8> frame(static_cast<std::size_t>(hdr_len) + cfg.fragment_size);
|
||||
|
||||
do {
|
||||
hdr.sequence = adapter_.audio_sequence_++;
|
||||
hdr.sequence = m_adapter.m_audio_sequence++;
|
||||
} while (!hdr.sequence);
|
||||
|
||||
encode_header(hdr, frame.data());
|
||||
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)
|
||||
return err;
|
||||
}
|
||||
@@ -250,18 +250,18 @@ auto client::send(std::span<u8 const> pkt, bool acknowledge) -> int
|
||||
{
|
||||
gip_header hdr{};
|
||||
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());
|
||||
|
||||
if (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
|
||||
{
|
||||
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,
|
||||
int audio_packet_count)
|
||||
: transport_(transport)
|
||||
, listener_(listener)
|
||||
, audio_packet_count_(audio_packet_count)
|
||||
: m_transport(transport)
|
||||
, m_listener(listener)
|
||||
, m_audio_packet_count(audio_packet_count)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -280,7 +280,7 @@ auto adapter::get_client(u8 id) -> client*
|
||||
if (id >= k_max_clients)
|
||||
return nullptr;
|
||||
|
||||
auto& slot = clients_[id];
|
||||
auto& slot = m_clients[id];
|
||||
if (!slot)
|
||||
slot = std::make_unique<client>(*this, id);
|
||||
|
||||
@@ -290,7 +290,7 @@ auto adapter::get_client(u8 id) -> client*
|
||||
auto adapter::client_count() const -> int
|
||||
{
|
||||
int n = 0;
|
||||
for (auto const& c : clients_)
|
||||
for (auto const& c : m_clients)
|
||||
if (c)
|
||||
++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);
|
||||
|
||||
while (!hdr.sequence)
|
||||
hdr.sequence = data_sequence_++;
|
||||
hdr.sequence = m_data_sequence++;
|
||||
|
||||
encode_header(hdr, frame.data());
|
||||
if (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)
|
||||
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)
|
||||
return err;
|
||||
|
||||
err = init_chunk_buffer(hdr, c.chunk_buf_in_);
|
||||
err = init_chunk_buffer(hdr, c.m_chunk_buf_in);
|
||||
if (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;
|
||||
}
|
||||
|
||||
@@ -376,7 +376,7 @@ auto adapter::init_chunk_buffer(gip_header const& hdr,
|
||||
|
||||
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;
|
||||
u32 len = buf->length - k_pkt_max_length;
|
||||
|
||||
@@ -401,24 +401,24 @@ auto adapter::request_identification(client& c) -> int
|
||||
{
|
||||
gip_header hdr{};
|
||||
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);
|
||||
}
|
||||
|
||||
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{};
|
||||
u8 pkt[9] = {};
|
||||
u32 len = ack.chunk_offset + ack.packet_length;
|
||||
|
||||
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.packet_length = sizeof(pkt);
|
||||
|
||||
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));
|
||||
|
||||
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
|
||||
{
|
||||
listener_.on_client_removed(c.id_);
|
||||
clients_[c.id_].reset();
|
||||
m_listener.on_client_removed(c.m_id);
|
||||
m_clients[c.m_id].reset();
|
||||
}
|
||||
|
||||
auto adapter::free_client_info(client& c) -> void
|
||||
{
|
||||
c.client_commands_.reset();
|
||||
c.firmware_versions_.reset();
|
||||
c.audio_formats_.reset();
|
||||
c.capabilities_out_.reset();
|
||||
c.capabilities_in_.reset();
|
||||
c.classes_.clear();
|
||||
c.interfaces_.reset();
|
||||
c.hid_descriptor_.reset();
|
||||
c.m_client_commands.reset();
|
||||
c.m_firmware_versions.reset();
|
||||
c.m_audio_formats.reset();
|
||||
c.m_capabilities_out.reset();
|
||||
c.m_capabilities_in.reset();
|
||||
c.m_classes.clear();
|
||||
c.m_interfaces.reset();
|
||||
c.m_hid_descriptor.reset();
|
||||
}
|
||||
|
||||
auto adapter::add_client(client& c) -> void
|
||||
{
|
||||
log_msg(log_level::info, "gip: client %u identified (vendor 0x%04x, "
|
||||
"product 0x%04x)",
|
||||
c.id_, c.hardware_.vendor, c.hardware_.product);
|
||||
listener_.on_client_added(c);
|
||||
c.m_id, c.m_hardware.vendor, c.m_hardware.product);
|
||||
m_listener.on_client_added(c);
|
||||
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.fragment_size = cfg.buffer_size / audio_packet_count_;
|
||||
cfg.fragment_size = cfg.buffer_size / m_audio_packet_count;
|
||||
|
||||
gip_header hdr{};
|
||||
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{};
|
||||
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;
|
||||
|
||||
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{};
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
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)
|
||||
return err;
|
||||
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,
|
||||
void const* data) -> int
|
||||
{
|
||||
auto& buf = c.chunk_buf_out_;
|
||||
auto& buf = c.m_chunk_buf_out;
|
||||
|
||||
if (!buf) {
|
||||
// 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;
|
||||
|
||||
auto const* p = static_cast<u8 const*>(data);
|
||||
auto& buf = c.chunk_buf_in_;
|
||||
auto& buf = c.m_chunk_buf_in;
|
||||
|
||||
if (!buf)
|
||||
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_minor = load_le16(p + 14);
|
||||
|
||||
if (!c.hardware_.vendor && !c.hardware_.product && !c.hardware_.version) {
|
||||
c.hardware_.vendor = vendor;
|
||||
c.hardware_.product = product;
|
||||
c.hardware_.version = static_cast<u16>((fw_major << 8) | fw_minor);
|
||||
if (!c.m_hardware.vendor && !c.m_hardware.product && !c.m_hardware.version) {
|
||||
c.m_hardware.vendor = vendor;
|
||||
c.m_hardware.product = product;
|
||||
c.m_hardware.version = static_cast<u16>((fw_major << 8) | fw_minor);
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
listener_.on_battery(c, (status >> 2) & 0x3, status & 0x3);
|
||||
m_listener.on_battery(c, (status >> 2) & 0x3, status & 0x3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -661,7 +661,7 @@ auto adapter::handle_pkt_identify(client& c, void const* data, u32 len) -> int
|
||||
if (len < 32)
|
||||
return -EINVAL;
|
||||
|
||||
if (!c.classes_.empty()) {
|
||||
if (!c.m_classes.empty()) {
|
||||
log_msg(log_level::warn, "gip: client already identified");
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
listener_.on_guide_button(c, p[0] != 0);
|
||||
m_listener.on_guide_button(c, p[0] != 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -731,41 +731,41 @@ auto adapter::handle_pkt_audio_control(client& c, void const* data, u32 len) ->
|
||||
case 0x00: // volume chat
|
||||
if (len != 5)
|
||||
return -EINVAL;
|
||||
listener_.on_audio_volume(c, p[4], p[3]);
|
||||
m_listener.on_audio_volume(c, p[4], p[3]);
|
||||
return 0;
|
||||
case 0x01: // format chat
|
||||
if (len != 2)
|
||||
return -EINVAL;
|
||||
if (p[1] != GIP_AUD_FORMAT_CHAT_24KHZ || c.audio_config_in_.buffer_size ||
|
||||
c.audio_config_out_.buffer_size) {
|
||||
if (p[1] != GIP_AUD_FORMAT_CHAT_24KHZ || c.m_audio_config_in.buffer_size ||
|
||||
c.m_audio_config_out.buffer_size) {
|
||||
return -EPROTO;
|
||||
}
|
||||
if (make_audio_config(c.audio_config_in_))
|
||||
if (make_audio_config(c.m_audio_config_in))
|
||||
return -EINVAL;
|
||||
if (make_audio_config(c.audio_config_out_))
|
||||
if (make_audio_config(c.m_audio_config_out))
|
||||
return -EINVAL;
|
||||
listener_.on_audio_ready(c);
|
||||
m_listener.on_audio_ready(c);
|
||||
return 0;
|
||||
case 0x02: // format
|
||||
if (len != 3)
|
||||
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;
|
||||
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",
|
||||
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);
|
||||
}
|
||||
if (make_audio_config(c.audio_config_in_))
|
||||
if (make_audio_config(c.m_audio_config_in))
|
||||
return -EINVAL;
|
||||
if (make_audio_config(c.audio_config_out_))
|
||||
if (make_audio_config(c.m_audio_config_out))
|
||||
return -EINVAL;
|
||||
listener_.on_audio_ready(c);
|
||||
m_listener.on_audio_ready(c);
|
||||
return 0;
|
||||
case 0x03: // volume
|
||||
if (len != 8)
|
||||
return -EINVAL;
|
||||
listener_.on_audio_volume(c, p[4], p[2]);
|
||||
m_listener.on_audio_volume(c, p[4], p[2]);
|
||||
return 0;
|
||||
default:
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -791,7 +791,7 @@ auto adapter::handle_pkt_audio_samples(client& c, void const* data, u32 len) ->
|
||||
return -EINVAL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
return err;
|
||||
}
|
||||
c.client_commands_ = std::move(cmds);
|
||||
c.m_client_commands = std::move(cmds);
|
||||
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);
|
||||
return err;
|
||||
}
|
||||
c.firmware_versions_ = std::move(vers);
|
||||
c.m_firmware_versions = std::move(vers);
|
||||
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);
|
||||
return err;
|
||||
}
|
||||
c.audio_formats_ = std::move(fmts);
|
||||
c.m_audio_formats = std::move(fmts);
|
||||
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);
|
||||
return err;
|
||||
}
|
||||
c.capabilities_out_ = std::move(caps);
|
||||
c.m_capabilities_out = std::move(caps);
|
||||
|
||||
err = parse_info_element(data, offsets[4], 1, caps);
|
||||
if (err) {
|
||||
log_msg(log_level::error, "gip: parse capabilities in failed: %d", err);
|
||||
return err;
|
||||
}
|
||||
c.capabilities_in_ = std::move(caps);
|
||||
c.m_capabilities_in = std::move(caps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -893,7 +893,7 @@ auto adapter::parse_classes(client& c, std::span<u8 const> data, u16 offset) ->
|
||||
if (!count)
|
||||
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)
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
c.classes_.emplace_back(
|
||||
c.m_classes.emplace_back(
|
||||
reinterpret_cast<char const*>(data.data() + 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);
|
||||
return err;
|
||||
}
|
||||
c.interfaces_ = std::move(intfs);
|
||||
c.m_interfaces = std::move(intfs);
|
||||
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);
|
||||
return err;
|
||||
}
|
||||
c.hid_descriptor_ = std::move(desc);
|
||||
c.m_hid_descriptor = std::move(desc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+20
-20
@@ -55,7 +55,7 @@ auto read_firmware_file(char const *path) -> std::optional<std::vector<std::uint
|
||||
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
|
||||
{
|
||||
@@ -66,7 +66,7 @@ auto chip::read_register(std::uint32_t addr) -> std::uint32_t
|
||||
}
|
||||
|
||||
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 & 0xFFFF),
|
||||
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];
|
||||
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 & 0xFFFF),
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
nullptr, 0);
|
||||
}
|
||||
@@ -565,17 +565,17 @@ auto chip::switch_channel(channel const *chan) -> int
|
||||
auto chip::evaluate_channels() -> int
|
||||
{
|
||||
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++) {
|
||||
if (auto err = get_channel_power(&channels_[i]); err != 0)
|
||||
if (auto err = get_channel_power(&m_channels[i]); err != 0)
|
||||
return err;
|
||||
if (auto err = switch_channel(&channels_[i]); err != 0)
|
||||
if (auto err = switch_channel(&m_channels[i]); err != 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
// The last channel may not be the best one.
|
||||
current_channel_ = channels_.back();
|
||||
m_current_channel = m_channels.back();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -591,8 +591,8 @@ auto chip::init_channels() -> int
|
||||
// Disable promiscuous mode.
|
||||
write_register(mt_rx_filtr_cfg, 0x017f17);
|
||||
|
||||
current_channel_.scan = true;
|
||||
if (auto err = switch_channel(¤t_channel_); err != 0)
|
||||
m_current_channel.scan = true;
|
||||
if (auto err = switch_channel(&m_current_channel); err != 0)
|
||||
return err;
|
||||
|
||||
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)
|
||||
return err;
|
||||
|
||||
current_channel_.scan = false;
|
||||
if (auto err = switch_channel(¤t_channel_); err != 0)
|
||||
m_current_channel.scan = false;
|
||||
if (auto err = switch_channel(&m_current_channel); err != 0)
|
||||
return err;
|
||||
|
||||
return set_channel_candidates();
|
||||
@@ -667,10 +667,10 @@ auto chip::set_channel_candidates() -> int
|
||||
};
|
||||
|
||||
append(1);
|
||||
append(current_channel_.index);
|
||||
append(m_current_channel.index);
|
||||
append(num_channels - 1);
|
||||
for (auto const &c : channels_)
|
||||
if (c.index != current_channel_.index)
|
||||
for (auto const &c : m_channels)
|
||||
if (c.index != m_current_channel.index)
|
||||
append(c.index);
|
||||
|
||||
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];
|
||||
xone::store_le32(payload + 0, static_cast<std::uint32_t>(wow_feature::wow_enable));
|
||||
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));
|
||||
}
|
||||
@@ -762,7 +762,7 @@ auto chip::resume_radio() -> int
|
||||
if (auto err = set_wow_enable(false); err != 0)
|
||||
return err;
|
||||
|
||||
if (auto err = switch_channel(¤t_channel_); err != 0)
|
||||
if (auto err = switch_channel(&m_current_channel); err != 0)
|
||||
return err;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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_cmd_type, 0);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+93
-93
@@ -144,28 +144,28 @@ auto transport::probe(frame_callback frames, disconnect_callback disconnected) -
|
||||
void transport::stop_pump()
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_->lock);
|
||||
if (state_->stopping)
|
||||
std::lock_guard<std::mutex> lock(m_state->lock);
|
||||
if (m_state->stopping)
|
||||
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);
|
||||
|
||||
if (!state_->thread_started)
|
||||
if (!m_state->thread_started)
|
||||
return;
|
||||
|
||||
CFRunLoopRef runloop = nullptr;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(state_->lock);
|
||||
state_->cv.wait(lock, [this] { return state_->loop_ready && state_->in_flight == 0; });
|
||||
runloop = state_->runloop;
|
||||
std::unique_lock<std::mutex> lock(m_state->lock);
|
||||
m_state->cv.wait(lock, [this] { return m_state->loop_ready && m_state->in_flight == 0; });
|
||||
runloop = m_state->runloop;
|
||||
}
|
||||
|
||||
// The reader thread is joined below; no callback can run after this.
|
||||
CFRunLoopStop(runloop);
|
||||
state_->thread.join();
|
||||
m_state->thread.join();
|
||||
}
|
||||
|
||||
auto transport::re_enumerate() -> int
|
||||
@@ -177,65 +177,65 @@ auto transport::re_enumerate() -> int
|
||||
// references while the kernel tears them down.
|
||||
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) {
|
||||
xone::log_msg(log_level::error, "usb: re-enumerate failed (%d)", kr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
// 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");
|
||||
return 0;
|
||||
}
|
||||
transport::~transport()
|
||||
{
|
||||
if (!state_)
|
||||
if (!m_state)
|
||||
return;
|
||||
|
||||
stop_pump();
|
||||
|
||||
// Release the termination watch and async event sources.
|
||||
if (state_->termination_iter)
|
||||
IOObjectRelease(state_->termination_iter);
|
||||
if (state_->notify_port)
|
||||
IONotificationPortDestroy(state_->notify_port);
|
||||
if (m_state->termination_iter)
|
||||
IOObjectRelease(m_state->termination_iter);
|
||||
if (m_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.
|
||||
if (state_->service)
|
||||
IOObjectRelease(state_->service);
|
||||
if (m_state->service)
|
||||
IOObjectRelease(m_state->service);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto *source : state_->sources)
|
||||
for (auto *source : m_state->sources)
|
||||
CFRelease(source);
|
||||
|
||||
// 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)->Release(conn.iface_ref);
|
||||
IODestroyPlugInInterface(conn.iodev);
|
||||
}
|
||||
|
||||
// Close the device connection.
|
||||
if (state_->dev_ref) {
|
||||
if (state_->dev_opened)
|
||||
(*state_->dev_ref)->USBDeviceClose(state_->dev_ref);
|
||||
(*state_->dev_ref)->Release(state_->dev_ref);
|
||||
if (m_state->dev_ref) {
|
||||
if (m_state->dev_opened)
|
||||
(*m_state->dev_ref)->USBDeviceClose(m_state->dev_ref);
|
||||
(*m_state->dev_ref)->Release(m_state->dev_ref);
|
||||
}
|
||||
if (state_->dev_iodev)
|
||||
IODestroyPlugInInterface(state_->dev_iodev);
|
||||
if (m_state->dev_iodev)
|
||||
IODestroyPlugInInterface(m_state->dev_iodev);
|
||||
|
||||
if (state_->service)
|
||||
IOObjectRelease(state_->service);
|
||||
if (m_state->service)
|
||||
IOObjectRelease(m_state->service);
|
||||
}
|
||||
|
||||
auto transport::open(frame_callback frames, disconnect_callback disconnected) -> bool
|
||||
{
|
||||
state_ = std::make_unique<state>();
|
||||
state_->frames = std::move(frames);
|
||||
state_->disconnected = std::move(disconnected);
|
||||
m_state = std::make_unique<state>();
|
||||
m_state->frames = std::move(frames);
|
||||
m_state->disconnected = std::move(disconnected);
|
||||
|
||||
// Find the dongle service (class match, filter by VID/PID).
|
||||
io_iterator_t iter = 0;
|
||||
@@ -250,8 +250,8 @@ auto transport::open(frame_callback frames, disconnect_callback disconnected) ->
|
||||
break;
|
||||
auto vp = read_vid_pid(service);
|
||||
if (vp && is_dongle(*vp)) {
|
||||
state_->service = service;
|
||||
state_->pid = vp->pid;
|
||||
m_state->service = service;
|
||||
m_state->pid = vp->pid;
|
||||
found = true;
|
||||
} else {
|
||||
IOObjectRelease(service);
|
||||
@@ -263,32 +263,32 @@ auto transport::open(frame_callback frames, disconnect_callback disconnected) ->
|
||||
|
||||
// Open the device connection.
|
||||
SInt32 score = 0;
|
||||
kr = IOCreatePlugInInterfaceForService(state_->service, kIOUSBDeviceUserClientTypeID,
|
||||
kIOCFPlugInInterfaceID, &state_->dev_iodev, &score);
|
||||
kr = IOCreatePlugInInterfaceForService(m_state->service, kIOUSBDeviceUserClientTypeID,
|
||||
kIOCFPlugInInterfaceID, &m_state->dev_iodev, &score);
|
||||
if (kr != kIOReturnSuccess) {
|
||||
xone::log_msg(log_level::error, "usb: create device interface failed (%d)", kr);
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
if (hr != S_OK || !slot) {
|
||||
xone::log_msg(log_level::error, "usb: query device interface failed");
|
||||
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) {
|
||||
xone::log_msg(log_level::error, "usb: open device failed (%d)", kr);
|
||||
return false;
|
||||
}
|
||||
state_->dev_opened = true;
|
||||
m_state->dev_opened = true;
|
||||
|
||||
// Reset the chip so it starts from the boot ROM (port of the
|
||||
// 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) {
|
||||
xone::log_msg(log_level::error, "usb: reset device failed (%d)", kr);
|
||||
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.
|
||||
io_iterator_t children = 0;
|
||||
kr = IORegistryEntryGetChildIterator(state_->service, kIOServicePlane, &children);
|
||||
kr = IORegistryEntryGetChildIterator(m_state->service, kIOServicePlane, &children);
|
||||
if (kr != kIOReturnSuccess)
|
||||
return false;
|
||||
|
||||
@@ -309,57 +309,57 @@ auto transport::open(frame_callback frames, disconnect_callback disconnected) ->
|
||||
}
|
||||
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)",
|
||||
state_->in_cmd_pipe.has_value(), state_->in_wlan_pipe.has_value(),
|
||||
state_->out_pipe.has_value());
|
||||
m_state->in_cmd_pipe.has_value(), m_state->in_wlan_pipe.has_value(),
|
||||
m_state->out_pipe.has_value());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Async completion dispatch for the opened interfaces.
|
||||
for (auto &conn : state_->ifaces) {
|
||||
for (auto &conn : m_state->ifaces) {
|
||||
CFRunLoopSourceRef source = nullptr;
|
||||
if ((*conn.iface_ref)->CreateInterfaceAsyncEventSource(conn.iface_ref, &source)
|
||||
== kIOReturnSuccess
|
||||
&& source)
|
||||
state_->sources.push_back(source);
|
||||
m_state->sources.push_back(source);
|
||||
}
|
||||
|
||||
// Watch for the dongle going away (unplug or chip reconnect). The
|
||||
// matching dictionary is consumed by this call.
|
||||
state_->notify_port = IONotificationPortCreate(0);
|
||||
kr = IOServiceAddMatchingNotification(state_->notify_port, kIOTerminatedNotification,
|
||||
m_state->notify_port = IONotificationPortCreate(0);
|
||||
kr = IOServiceAddMatchingNotification(m_state->notify_port, kIOTerminatedNotification,
|
||||
IOServiceMatching("IOUSBDevice"),
|
||||
on_dongle_terminated, this,
|
||||
&state_->termination_iter);
|
||||
&m_state->termination_iter);
|
||||
if (kr != kIOReturnSuccess) {
|
||||
xone::log_msg(log_level::error, "usb: add termination notification failed (%d)", kr);
|
||||
return false;
|
||||
}
|
||||
|
||||
state_->thread = std::thread([this] { worker_loop(); });
|
||||
state_->thread_started = true;
|
||||
m_state->thread = std::thread([this] { worker_loop(); });
|
||||
m_state->thread_started = true;
|
||||
|
||||
// Submit the initial async reads (EP 0x05 IN and EP 0x04 IN). Reserve so
|
||||
// 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,
|
||||
std::uint8_t ep, std::size_t buf_len) -> bool {
|
||||
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) });
|
||||
if (!submit_read(&state_->slots.back()))
|
||||
if (!submit_read(&m_state->slots.back()))
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -387,7 +387,7 @@ auto transport::open_interface(io_service_t child) -> bool
|
||||
return false;
|
||||
}
|
||||
|
||||
state_->ifaces.push_back(conn);
|
||||
m_state->ifaces.push_back(conn);
|
||||
|
||||
// Scan the interface's pipes for the endpoints we need.
|
||||
UInt8 num_pipes = 0;
|
||||
@@ -403,12 +403,12 @@ auto transport::open_interface(io_service_t child) -> bool
|
||||
continue;
|
||||
|
||||
std::uint8_t ep = static_cast<std::uint8_t>(number);
|
||||
if (direction == kUSBIn && ep == ep_in_cmd && !state_->in_cmd_pipe.has_value())
|
||||
state_->in_cmd_pipe = { conn.iface_ref, i };
|
||||
else if (direction == kUSBIn && ep == ep_in_wlan && !state_->in_wlan_pipe.has_value())
|
||||
state_->in_wlan_pipe = { conn.iface_ref, i };
|
||||
else if (direction == kUSBOut && ep == ep_out && !state_->out_pipe.has_value())
|
||||
state_->out_pipe = { conn.iface_ref, i };
|
||||
if (direction == kUSBIn && ep == ep_in_cmd && !m_state->in_cmd_pipe.has_value())
|
||||
m_state->in_cmd_pipe = { conn.iface_ref, i };
|
||||
else if (direction == kUSBIn && ep == ep_in_wlan && !m_state->in_wlan_pipe.has_value())
|
||||
m_state->in_wlan_pipe = { conn.iface_ref, i };
|
||||
else if (direction == kUSBOut && ep == ep_out && !m_state->out_pipe.has_value())
|
||||
m_state->out_pipe = { conn.iface_ref, i };
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -416,7 +416,7 @@ auto transport::open_interface(io_service_t child) -> bool
|
||||
|
||||
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,
|
||||
@@ -432,7 +432,7 @@ auto transport::send_vendor_request(vendor_request req, bool is_read, std::uint1
|
||||
request.wLength = static_cast<UInt16>(len);
|
||||
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) {
|
||||
xone::log_msg(log_level::error, "usb: vendor request 0x%02x failed (%d)",
|
||||
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 &pipe = state_->out_pipe.value();
|
||||
auto &pipe = m_state->out_pipe.value();
|
||||
IOReturn ret = (*pipe.iface_ref)->WritePipe(pipe.iface_ref, pipe.ref,
|
||||
const_cast<void *>(data), static_cast<UInt32>(len));
|
||||
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
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_->lock);
|
||||
if (state_->stopping)
|
||||
std::lock_guard<std::mutex> lock(m_state->lock);
|
||||
if (m_state->stopping)
|
||||
return false;
|
||||
state_->in_flight++;
|
||||
m_state->in_flight++;
|
||||
}
|
||||
|
||||
IOReturn ret = (*slot->iface_ref)->ReadPipeAsync(slot->iface_ref, slot->pipe_ref,
|
||||
slot->buf.data(), static_cast<UInt32>(slot->buf.size()),
|
||||
on_read_completion, slot);
|
||||
if (ret != kIOReturnSuccess) {
|
||||
std::lock_guard<std::mutex> lock(state_->lock);
|
||||
state_->in_flight--;
|
||||
state_->cv.notify_all();
|
||||
std::lock_guard<std::mutex> lock(m_state->lock);
|
||||
m_state->in_flight--;
|
||||
m_state->cv.notify_all();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -480,16 +480,16 @@ auto transport::submit_read(read_slot *slot) -> bool
|
||||
void transport::worker_loop()
|
||||
{
|
||||
CFRunLoopRef runloop = CFRunLoopGetCurrent();
|
||||
for (auto *source : state_->sources)
|
||||
for (auto *source : m_state->sources)
|
||||
CFRunLoopAddSource(runloop, source, kCFRunLoopDefaultMode);
|
||||
CFRunLoopAddSource(runloop, IONotificationPortGetRunLoopSource(state_->notify_port),
|
||||
CFRunLoopAddSource(runloop, IONotificationPortGetRunLoopSource(m_state->notify_port),
|
||||
kCFRunLoopDefaultMode);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_->lock);
|
||||
state_->runloop = runloop;
|
||||
state_->loop_ready = true;
|
||||
state_->cv.notify_all();
|
||||
std::lock_guard<std::mutex> lock(m_state->lock);
|
||||
m_state->runloop = runloop;
|
||||
m_state->loop_ready = true;
|
||||
m_state->cv.notify_all();
|
||||
}
|
||||
|
||||
CFRunLoopRun();
|
||||
@@ -497,13 +497,13 @@ void transport::worker_loop()
|
||||
|
||||
void transport::handle_read(read_slot *slot, IOReturn result, std::size_t len)
|
||||
{
|
||||
if (result == kIOReturnSuccess && len > 0 && state_->frames)
|
||||
state_->frames(slot->ep, slot->buf.data(), len);
|
||||
if (result == kIOReturnSuccess && len > 0 && m_state->frames)
|
||||
m_state->frames(slot->ep, slot->buf.data(), len);
|
||||
|
||||
std::lock_guard<std::mutex> lock(state_->lock);
|
||||
if (state_->stopping) {
|
||||
state_->in_flight--;
|
||||
state_->cv.notify_all();
|
||||
std::lock_guard<std::mutex> lock(m_state->lock);
|
||||
if (m_state->stopping) {
|
||||
m_state->in_flight--;
|
||||
m_state->cv.notify_all();
|
||||
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()),
|
||||
on_read_completion, slot);
|
||||
if (ret != kIOReturnSuccess) {
|
||||
state_->in_flight--;
|
||||
state_->cv.notify_all();
|
||||
m_state->in_flight--;
|
||||
m_state->cv.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,11 +520,11 @@ void transport::handle_disconnected()
|
||||
{
|
||||
disconnect_callback callback;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_->lock);
|
||||
if (state_->stopping || state_->disconnected_notified)
|
||||
std::lock_guard<std::mutex> lock(m_state->lock);
|
||||
if (m_state->stopping || m_state->disconnected_notified)
|
||||
return;
|
||||
state_->disconnected_notified = true;
|
||||
callback = state_->disconnected;
|
||||
m_state->disconnected_notified = true;
|
||||
callback = m_state->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)
|
||||
break;
|
||||
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;
|
||||
IOObjectRelease(service);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user