Skip to content

Commit

Permalink
Support MAC address as the identifier for bluetooth devices
Browse files Browse the repository at this point in the history
  • Loading branch information
stackia committed May 12, 2023
1 parent e3d0c23 commit 7e2bc3e
Show file tree
Hide file tree
Showing 23 changed files with 210 additions and 53 deletions.
4 changes: 3 additions & 1 deletion src/apps/SettingsWindow/src/View/DeviceSelectorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ struct DeviceSelectorView: View {
Button(action: {
selectedDevice = connectedDeviceSetting.connectedDevice
}) {
let noId = connectedDeviceSetting.connectedDevice.vendorId == 0 && connectedDeviceSetting.connectedDevice.productId == 0
let label = noId ? connectedDeviceSetting.connectedDevice.deviceAddress : "\(String(connectedDeviceSetting.connectedDevice.vendorId)),\(String(connectedDeviceSetting.connectedDevice.productId))"
HStack {
Text(
"""
\(connectedDeviceSetting.connectedDevice.productName) \
(\(connectedDeviceSetting.connectedDevice.manufacturerName)) \
[\(String(connectedDeviceSetting.connectedDevice.vendorId)),\(String(connectedDeviceSetting.connectedDevice.productId))]
[\(label)]
"""
)

Expand Down
58 changes: 36 additions & 22 deletions src/apps/SettingsWindow/src/View/DevicesView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,30 +94,44 @@ struct DevicesView: View {

if connectedDeviceSetting.connectedDevice.transport != "FIFO" {
VStack(alignment: .trailing, spacing: 4.0) {
HStack(alignment: .firstTextBaseline, spacing: 0) {
Spacer()

Text("Vendor ID: ")

Text(
String(
format: "%5d (0x%04x)",
connectedDeviceSetting.connectedDevice.vendorId,
connectedDeviceSetting.connectedDevice.vendorId)
)
if connectedDeviceSetting.connectedDevice.vendorId != 0 {
HStack(alignment: .firstTextBaseline, spacing: 0) {
Spacer()

Text("Vendor ID: ")

Text(
String(
format: "%5d (0x%04x)",
connectedDeviceSetting.connectedDevice.vendorId,
connectedDeviceSetting.connectedDevice.vendorId)
)
}
}

HStack(alignment: .center, spacing: 0) {
Spacer()

Text("Product ID: ")

Text(
String(
format: "%5d (0x%04x)",
connectedDeviceSetting.connectedDevice.productId,
connectedDeviceSetting.connectedDevice.productId)
)
if connectedDeviceSetting.connectedDevice.productId != 0 {
HStack(alignment: .center, spacing: 0) {
Spacer()

Text("Product ID: ")

Text(
String(
format: "%5d (0x%04x)",
connectedDeviceSetting.connectedDevice.productId,
connectedDeviceSetting.connectedDevice.productId)
)
}
}

if !connectedDeviceSetting.connectedDevice.deviceAddress.isEmpty {
HStack(alignment: .center, spacing: 0) {
Spacer()

Text("Device Address: ")

Text(connectedDeviceSetting.connectedDevice.deviceAddress)
}
}
}
.font(.custom("Menlo", size: 12.0))
Expand Down
1 change: 1 addition & 0 deletions src/apps/share/swift/LibKrbn/ConnectedDevices.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ extension LibKrbn {
transport: transport,
vendorId: libkrbn_connected_devices_get_vendor_id(libkrbnConnectedDevices, i),
productId: libkrbn_connected_devices_get_product_id(libkrbnConnectedDevices, i),
deviceAddress: libkrbn_connected_devices_get_device_address(libkrbnConnectedDevices, i),
isKeyboard: libkrbn_connected_devices_get_is_keyboard(libkrbnConnectedDevices, i),
isPointingDevice: libkrbn_connected_devices_get_is_pointing_device(
libkrbnConnectedDevices, i),
Expand Down
4 changes: 4 additions & 0 deletions src/apps/share/swift/LibKrbn/Models/ConnectedDevice.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extension LibKrbn {
let transport: String
let vendorId: UInt64
let productId: UInt64
let deviceAddress: String
let isKeyboard: Bool
let isPointingDevice: Bool
let isBuiltInKeyboard: Bool
Expand All @@ -25,6 +26,7 @@ extension LibKrbn {
transport: String,
vendorId: UInt64,
productId: UInt64,
deviceAddress: UnsafePointer<CChar>,
isKeyboard: Bool,
isPointingDevice: Bool,
isBuiltInKeyboard: Bool,
Expand All @@ -38,6 +40,7 @@ extension LibKrbn {
self.transport = transport
self.vendorId = vendorId
self.productId = productId
self.deviceAddress = String(cString: deviceAddress)
self.isKeyboard = isKeyboard
self.isPointingDevice = isPointingDevice
self.isBuiltInKeyboard = isBuiltInKeyboard
Expand All @@ -49,6 +52,7 @@ extension LibKrbn {
capacity: 1)
libkrbnDeviceIdentifiers.pointee.vendor_id = vendorId
libkrbnDeviceIdentifiers.pointee.product_id = productId
libkrbnDeviceIdentifiers.pointee.device_address = deviceAddress
libkrbnDeviceIdentifiers.pointee.is_keyboard = isKeyboard
libkrbnDeviceIdentifiers.pointee.is_pointing_device = isPointingDevice
}
Expand Down
1 change: 1 addition & 0 deletions src/lib/libkrbn/include/libkrbn/impl/libkrbn_cpp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class libkrbn_cpp final {
static krbn::device_identifiers make_device_identifiers(const libkrbn_device_identifiers& device_identifiers) {
krbn::device_identifiers identifiers(pqrs::hid::vendor_id::value_t(device_identifiers.vendor_id),
pqrs::hid::product_id::value_t(device_identifiers.product_id),
device_identifiers.device_address ? std::string(device_identifiers.device_address) : "",
device_identifiers.is_keyboard,
device_identifiers.is_pointing_device);
return identifiers;
Expand Down
2 changes: 2 additions & 0 deletions src/lib/libkrbn/include/libkrbn/libkrbn.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extern "C" {
typedef struct {
uint64_t vendor_id;
uint64_t product_id;
const char* device_address;
bool is_keyboard;
bool is_pointing_device;
} libkrbn_device_identifiers;
Expand Down Expand Up @@ -247,6 +248,7 @@ bool libkrbn_connected_devices_get_device_identifiers(libkrbn_connected_devices*
libkrbn_device_identifiers* device_identifiers);
uint64_t libkrbn_connected_devices_get_vendor_id(libkrbn_connected_devices* p, size_t index);
uint64_t libkrbn_connected_devices_get_product_id(libkrbn_connected_devices* p, size_t index);
const char* libkrbn_connected_devices_get_device_address(libkrbn_connected_devices* p, size_t index);
bool libkrbn_connected_devices_get_is_keyboard(libkrbn_connected_devices* p, size_t index);
bool libkrbn_connected_devices_get_is_pointing_device(libkrbn_connected_devices* p, size_t index);
bool libkrbn_connected_devices_get_is_built_in_keyboard(libkrbn_connected_devices* p, size_t index);
Expand Down
10 changes: 10 additions & 0 deletions src/lib/libkrbn/src/libkrbn_connected_devices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ uint64_t libkrbn_connected_devices_get_product_id(libkrbn_connected_devices* p,
return 0;
}

const char* libkrbn_connected_devices_get_device_address(libkrbn_connected_devices* p, size_t index) {
if (auto c = reinterpret_cast<libkrbn_connected_devices_class*>(p)) {
const auto& devices = c->get_connected_devices().get_devices();
if (index < devices.size()) {
return devices[index].get_identifiers().get_device_address().c_str();
}
}
return nullptr;
}

bool libkrbn_connected_devices_get_is_keyboard(libkrbn_connected_devices* p, size_t index) {
if (auto c = reinterpret_cast<libkrbn_connected_devices_class*>(p)) {
const auto& devices = c->get_connected_devices().get_devices();
Expand Down
16 changes: 16 additions & 0 deletions src/share/device_properties.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class device_properties final {
product_ = hid_device.find_product();
serial_number_ = hid_device.find_serial_number();
transport_ = hid_device.find_transport();
device_address_ = hid_device.find_device_address();
is_keyboard_ = iokit_utility::is_keyboard(hid_device);
is_pointing_device_ = iokit_utility::is_pointing_device(hid_device);

Expand Down Expand Up @@ -138,6 +139,9 @@ class device_properties final {
if (transport_) {
json["transport"] = *transport_;
}
if (device_address_) {
json["device_address"] = *device_address_;
}
if (is_keyboard_) {
json["is_keyboard"] = *is_keyboard_;
}
Expand Down Expand Up @@ -225,6 +229,16 @@ class device_properties final {
return *this;
}

std::optional<std::string> get_device_address(void) const {
return device_address_;
}

device_properties& set_device_address(const std::string& value) {
device_address_ = value;
update_device_identifiers();
return *this;
}

std::optional<device_id> get_device_id(void) const {
return device_id_;
}
Expand Down Expand Up @@ -341,6 +355,7 @@ class device_properties final {
device_identifiers_ = std::make_shared<device_identifiers>(
vendor_id_.value_or(pqrs::hid::vendor_id::value_t(0)),
product_id_.value_or(pqrs::hid::product_id::value_t(0)),
device_address_.value_or(""),
is_keyboard_.value_or(false),
is_pointing_device_.value_or(false));
}
Expand All @@ -353,6 +368,7 @@ class device_properties final {
std::optional<std::string> product_;
std::optional<std::string> serial_number_;
std::optional<std::string> transport_;
std::optional<std::string> device_address_;
std::optional<bool> is_keyboard_;
std::optional<bool> is_pointing_device_;
std::optional<bool> is_built_in_keyboard_;
Expand Down
10 changes: 10 additions & 0 deletions src/share/manipulator/conditions/device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class device final : public base {
std::optional<pqrs::hid::vendor_id::value_t> vendor_id;
std::optional<pqrs::hid::product_id::value_t> product_id;
std::optional<location_id> location_id;
std::optional<std::string> device_address;
std::optional<bool> is_keyboard;
std::optional<bool> is_pointing_device;
std::optional<bool> is_touch_bar;
Expand All @@ -132,6 +133,7 @@ class device final : public base {
return vendor_id ||
product_id ||
location_id ||
device_address ||
is_keyboard ||
is_pointing_device ||
is_touch_bar ||
Expand All @@ -154,6 +156,9 @@ class device final : public base {
if (location_id && location_id != device_properties.get_location_id().value_or(krbn::location_id(0))) {
return false;
}
if (device_address && device_address != device_properties.get_device_address().value_or("")) {
return false;
}
if (is_keyboard && is_keyboard != device_properties.get_is_keyboard().value_or(false)) {
return false;
}
Expand Down Expand Up @@ -199,6 +204,11 @@ class device final : public base {

d.location_id = location_id(value.get<int>());

} else if (key == "device_address") {
pqrs::json::requires_string(value, "identifiers entry `device_address`");

d.device_address = value.get<std::string>();

} else if (key == "is_keyboard") {
pqrs::json::requires_boolean(value, "identifiers entry `is_keyboard`");

Expand Down
19 changes: 19 additions & 0 deletions src/share/types/device_identifiers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@ class device_identifiers final {
public:
device_identifiers(void) : vendor_id_(pqrs::hid::vendor_id::value_t(0)),
product_id_(pqrs::hid::product_id::value_t(0)),
device_address_(""),
is_keyboard_(false),
is_pointing_device_(false) {
}

device_identifiers(pqrs::hid::vendor_id::value_t vendor_id,
pqrs::hid::product_id::value_t product_id,
std::string device_address,
bool is_keyboard,
bool is_pointing_device) : vendor_id_(vendor_id),
product_id_(product_id),
device_address_(device_address),
is_keyboard_(is_keyboard),
is_pointing_device_(is_pointing_device) {
}
Expand Down Expand Up @@ -47,6 +50,14 @@ class device_identifiers final {
product_id_ = value;
}

const std::string& get_device_address(void) const {
return device_address_;
}

void set_device_address(std::string value) {
device_address_ = value;
}

bool get_is_keyboard(void) const {
return is_keyboard_;
}
Expand All @@ -71,6 +82,7 @@ class device_identifiers final {
bool operator==(const device_identifiers& other) const {
return vendor_id_ == other.vendor_id_ &&
product_id_ == other.product_id_ &&
device_address_ == other.device_address_ &&
is_keyboard_ == other.is_keyboard_ &&
is_pointing_device_ == other.is_pointing_device_;
}
Expand All @@ -79,6 +91,7 @@ class device_identifiers final {
nlohmann::json json_;
pqrs::hid::vendor_id::value_t vendor_id_;
pqrs::hid::product_id::value_t product_id_;
std::string device_address_;
bool is_keyboard_;
bool is_pointing_device_;
};
Expand All @@ -87,6 +100,7 @@ inline void to_json(nlohmann::json& json, const device_identifiers& value) {
json = value.get_json();
json["vendor_id"] = type_safe::get(value.get_vendor_id());
json["product_id"] = type_safe::get(value.get_product_id());
json["device_address"] = value.get_device_address();
json["is_keyboard"] = value.get_is_keyboard();
json["is_pointing_device"] = value.get_is_pointing_device();
}
Expand All @@ -105,6 +119,11 @@ inline void from_json(const nlohmann::json& json, device_identifiers& value) {

value.set_product_id(v.get<pqrs::hid::product_id::value_t>());

} else if (k == "device_address") {
pqrs::json::requires_string(v, "`" + k + "`");

value.set_device_address(v.get<std::string>());

} else if (k == "is_keyboard") {
pqrs::json::requires_boolean(v, "`" + k + "`");

Expand Down
10 changes: 8 additions & 2 deletions tests/src/connected_devices/json/connected_devices.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"transport": "USB"
},
"identifiers": {
"device_address": "",
"is_keyboard": true,
"is_pointing_device": false,
"product_id": 5678,
Expand All @@ -22,6 +23,7 @@
"transport": "USB"
},
"identifiers": {
"device_address": "",
"is_keyboard": false,
"is_pointing_device": true,
"product_id": 5679,
Expand All @@ -38,6 +40,7 @@
"transport": "USB"
},
"identifiers": {
"device_address": "",
"is_keyboard": false,
"is_pointing_device": true,
"product_id": 6789,
Expand All @@ -54,6 +57,7 @@
"transport": "Bluetooth"
},
"identifiers": {
"device_address": "ec-ba-73-21-e6-f4",
"is_keyboard": true,
"is_pointing_device": false,
"product_id": 678,
Expand All @@ -70,6 +74,7 @@
"transport": "Bluetooth"
},
"identifiers": {
"device_address": "ec-ba-73-21-e6-f4",
"is_keyboard": false,
"is_pointing_device": true,
"product_id": 678,
Expand All @@ -86,10 +91,11 @@
"transport": "Bluetooth"
},
"identifiers": {
"device_address": "ec-ba-73-21-e6-f5",
"is_keyboard": true,
"is_pointing_device": false,
"product_id": 678,
"vendor_id": 1234
"product_id": 0,
"vendor_id": 0
},
"is_built_in_keyboard": false,
"is_built_in_touch_bar": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"transport": "USB"
},
"identifiers": {
"device_address": "",
"is_keyboard": true,
"is_pointing_device": false,
"product_id": 5678,
Expand Down
Loading

0 comments on commit 7e2bc3e

Please sign in to comment.