mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-30 00:37:23 +01:00
BluetoothRadio (macOS): detect more info
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -26,14 +26,14 @@ static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadio
|
||||
|
||||
const char* version = NULL;
|
||||
|
||||
switch (radio->lmpVersion)
|
||||
switch (radio->lmpVersion < 0 ? -radio->lmpVersion : radio->lmpVersion)
|
||||
{
|
||||
case 0: version = "1.0b"; break;
|
||||
case 1: version = "1.1"; break;
|
||||
case 2: version = "1.2"; break;
|
||||
case 3: version = "2.0 + EDR"; break;
|
||||
case 4: version = "2.1 + EDR"; break;
|
||||
case 5: version = "3.0 + HS"; break;
|
||||
case 3: version = "2.0"; break;
|
||||
case 4: version = "2.1"; break;
|
||||
case 5: version = "3.0"; break;
|
||||
case 6: version = "4.0"; break;
|
||||
case 7: version = "4.1"; break;
|
||||
case 8: version = "4.2"; break;
|
||||
@@ -49,9 +49,9 @@ static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadio
|
||||
ffPrintLogoAndKey(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY);
|
||||
|
||||
if (version)
|
||||
printf("Bluetooth %s (%s)\n", version, radio->vendor);
|
||||
printf("Bluetooth %s%s (%s)\n", version, (radio->lmpVersion < 0 ? "+" : ""), radio->vendor.chars);
|
||||
else
|
||||
fputs(radio->vendor, stdout);
|
||||
ffStrbufPutTo(&radio->vendor, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -61,7 +61,7 @@ static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadio
|
||||
{FF_FORMAT_ARG_TYPE_INT, &radio->lmpVersion, "lmp-version"},
|
||||
{FF_FORMAT_ARG_TYPE_INT, &radio->lmpSubversion, "lmp-subversion"},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, version, "version"},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, radio->vendor, "vendor"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &radio->vendor, "vendor"},
|
||||
{FF_FORMAT_ARG_TYPE_BOOL, &radio->discoverable, "discoverable"},
|
||||
{FF_FORMAT_ARG_TYPE_BOOL, &radio->connectable, "connectable"},
|
||||
}));
|
||||
@@ -102,6 +102,7 @@ void ffPrintBluetoothRadio(FFBluetoothRadioOptions* options)
|
||||
{
|
||||
ffStrbufDestroy(&radio->name);
|
||||
ffStrbufDestroy(&radio->address);
|
||||
ffStrbufDestroy(&radio->vendor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,15 +159,15 @@ void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions*
|
||||
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address);
|
||||
if (item->lmpVersion < 0)
|
||||
if (item->lmpVersion == INT_MIN)
|
||||
yyjson_mut_obj_add_null(doc, obj, "lmpVersion");
|
||||
else
|
||||
yyjson_mut_obj_add_int(doc, obj, "lmpVersion", item->lmpVersion);
|
||||
if (item->lmpSubversion < 0)
|
||||
if (item->lmpSubversion == INT_MIN)
|
||||
yyjson_mut_obj_add_null(doc, obj, "lmpSubversion");
|
||||
else
|
||||
yyjson_mut_obj_add_int(doc, obj, "lmpSubversion", item->lmpSubversion);
|
||||
yyjson_mut_obj_add_str(doc, obj, "vendor", item->vendor);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &item->vendor);
|
||||
yyjson_mut_obj_add_bool(doc, obj, "enabled", item->enabled);
|
||||
yyjson_mut_obj_add_bool(doc, obj, "discoverable", item->discoverable);
|
||||
yyjson_mut_obj_add_bool(doc, obj, "connectable", item->connectable);
|
||||
@@ -176,6 +177,7 @@ void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions*
|
||||
{
|
||||
ffStrbufDestroy(&radio->name);
|
||||
ffStrbufDestroy(&radio->address);
|
||||
ffStrbufDestroy(&radio->vendor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user