From 76424950e373d3b04ac3dd13019151bfba3e8423 Mon Sep 17 00:00:00 2001 From: sumuel Date: Mon, 17 Aug 2026 20:44:55 +0000 Subject: Add the files --- .../bluetoothradio/bluetoothradio_apple.m | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/detection/bluetoothradio/bluetoothradio_apple.m (limited to 'src/detection/bluetoothradio/bluetoothradio_apple.m') diff --git a/src/detection/bluetoothradio/bluetoothradio_apple.m b/src/detection/bluetoothradio/bluetoothradio_apple.m new file mode 100644 index 0000000..c5154ab --- /dev/null +++ b/src/detection/bluetoothradio/bluetoothradio_apple.m @@ -0,0 +1,69 @@ +#include "bluetoothradio.h" +#include "common/processing.h" + +#import + +// For some reason the official declaration of IOBluetoothHostController doesn't include property `controllers` +@interface IOBluetoothHostController() ++ (id)controllers; +@end + +const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) +{ + NSArray* ctrls = IOBluetoothHostController.controllers; + if(!ctrls) + return "IOBluetoothHostController.controllers returns nil"; + + 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"; + + 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 = FF_LIST_ADD(FFBluetoothRadioResult, *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; +} -- cgit v1.2.3