BluetoothRadio (macOS): detect more info

This commit is contained in:
李通洲
2024-07-29 16:32:36 +08:00
parent c14ba32b82
commit 0929b940c8
5 changed files with 78 additions and 34 deletions
@@ -6,9 +6,9 @@ typedef struct FFBluetoothRadioResult
{
FFstrbuf name;
FFstrbuf address;
FFstrbuf vendor;
int32_t lmpVersion;
int32_t lmpSubversion;
const char* vendor;
bool enabled;
bool discoverable;
bool connectable;
@@ -1,27 +1,69 @@
#include "bluetoothradio.h"
#include "common/processing.h"
#import <IOBluetooth/IOBluetooth.h>
// For some reason the official declaration of IOBluetoothHostController don't include property `controllers`
@interface IOBluetoothHostController()
+ (id)controllers;
@end
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothResult */)
{
IOBluetoothHostController* ctrl = IOBluetoothHostController.defaultController;
if(!ctrl)
return "IOBluetoothHostController.defaultController failed";
NSArray<IOBluetoothHostController*>* ctrls = IOBluetoothHostController.controllers;
if(!ctrls)
return "IOBluetoothHostController.controllers returns nil";
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, ctrl.nameAsString.UTF8String);
ffStrbufInitS(&device->address, ctrl.addressAsString.UTF8String);
device->lmpVersion = -1;
device->lmpSubversion = -1;
device->enabled = ctrl.powerState == kBluetoothHCIPowerStateON;
device->discoverable = false;
device->connectable = true;
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (ffProcessAppendStdOut(&buffer, (char* const[]) {
"system_profiler",
"SPBluetoothDataType",
"-xml",
"-detailLevel",
"basic",
NULL
}) != NULL)
return "Starting `system_profiler SPBluetoothDataType -xml -detailLevel basic` failed";
#ifdef __aarch64__
device->vendor = "Apple";
#else
device->vendor = "Unknown"; // Hackintosh?
#endif
NSArray* arr = [NSPropertyListSerialization propertyListWithData:[NSData dataWithBytes:buffer.chars length:buffer.length]
options:NSPropertyListImmutable
format:nil
error:nil];
if (!arr || !arr.count)
return "system_profiler SPBluetoothDataType returned an empty array";
for (IOBluetoothHostController* ctrl in ctrls)
{
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, ctrl.nameAsString.UTF8String);
ffStrbufInitS(&device->address, ctrl.addressAsString.UTF8String);
ffStrbufInitStatic(&device->vendor, "Apple");
device->lmpVersion = INT_MIN;
device->lmpSubversion = INT_MIN;
device->enabled = ctrl.powerState == kBluetoothHCIPowerStateON;
device->discoverable = false;
device->connectable = true;
for (NSDictionary* itemDict in arr[0][@"_items"])
{
NSDictionary* props = itemDict[@"controller_properties"];
if (!props) continue;
if (![ctrl.addressAsString isEqualToString:props[@"controller_address"]]) continue;
NSString* services = props[@"controller_supportedServices"];
if ([services containsString:@" LEA "])
device->lmpVersion = -11;
else if ([services containsString:@" GATT "])
device->lmpVersion = -6;
device->discoverable = ![props[@"controller_discoverable"] isEqualToString:@"attrib_off"];
ffStrbufSetS(&device->vendor, ((NSString*) props[@"controller_vendorID"]).UTF8String);
ffStrbufSubstrAfterFirstC(&device->vendor, '(');
ffStrbufTrimRight(&device->vendor, ')');
break;
}
}
return NULL;
}
@@ -65,9 +65,9 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
ffDBusGetString(dbus, &dictIter, &device->name);
else if(ffStrEquals(deviceProperty, "Manufacturer"))
{
uint16_t detection;
if (ffDBusGetUint16(dbus, &dictIter, &detection))
device->vendor = ffBluetoothRadioGetVendor(detection);
uint16_t vendorId;
if (ffDBusGetUint16(dbus, &dictIter, &vendorId))
ffStrbufSetStatic(&device->vendor, ffBluetoothRadioGetVendor(vendorId));
}
else if(ffStrEquals(deviceProperty, "Version"))
{
@@ -144,9 +144,9 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
device->lmpVersion = -1;
device->lmpSubversion = -1;
device->vendor = "Unknown";
ffStrbufInitStatic(&device->vendor, "Unknown");
device->lmpVersion = INT_MIN;
device->lmpSubversion = INT_MIN;
device->enabled = false;
while(true)
@@ -93,7 +93,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
device->lmpVersion = blri.radioInfo.lmpVersion;
device->lmpSubversion = blri.radioInfo.lmpSubversion;
device->vendor = ffBluetoothRadioGetVendor(blri.radioInfo.mfg);
ffStrbufSetStatic(&device->vendor, ffBluetoothRadioGetVendor(blri.radioInfo.mfg));
device->enabled = true;
device->connectable = ffBluetoothIsConnectable(hRadio);
device->discoverable = ffBluetoothIsDiscoverable(hRadio);