IOBluetoothDevice registerForConnectNotifications callbacks not working (no callbacks) when process run as daemon/root under Sonoma (works on Ventura)

No connection notifications callback for Bluetooth devices are called on Sonoma if process is run as daemon/system, works on Ventura. Seems to be some changes in TCC that now requires kTCCServiceBluetoothAlways in system TCC.db - but how to grant this?

Other calls on IOBluetoothDevice fails probably for the same reason.

Running as launch agent works as expected on both Sonoma and Ventura.

Code used os_log_t logHandle = 0;

@interface BluetoothConnection : NSObject { } @end

@implementation BluetoothConnection

-(id)init { self = [super init]; if (self) { IOBluetoothUserNotification* notification = [IOBluetoothDevice registerForConnectNotifications:self selector:@selector(deviceIsConnected:fromDevice:)]; if (notification == nil) { os_log_debug(logHandle, "registerForConnectNotifications failed"); } else { os_log_debug(logHandle, "registerForConnectNotifications %{public}@", notification); } } return self; }

-(void)deviceDidDisconnect:(IOBluetoothUserNotification*)notification fromDevice:(IOBluetoothDevice*)device { os_log_debug(logHandle, "%{public}@ (%{public}@) disconnected", [device name], [device addressString]); }

-(void)deviceIsConnected:(IOBluetoothUserNotification*)notification fromDevice:(IOBluetoothDevice*)device { os_log_debug(logHandle, "%{public}@ (%{public}@) connected (%d, %d)", [device name], [device addressString], device.deviceClassMajor, device.deviceClassMinor); [device registerForDisconnectNotification:self selector:@selector(deviceDidDisconnect:fromDevice:)]; } @end

int main(int argc, const char * argv[]) { @autoreleasepool { logHandle = os_log_create("SPX”, “BT”); BluetoothConnection *bluetoothConnection = [[BluetoothConnection alloc] init]; [[NSRunLoop currentRunLoop] run]; } return 0; }

Replies

Starting with Sonoma, access to IOBluetooth framework is gated by TCC (Transparency, Consent, and Control) prompts.

TCC is not available for root daemons in macOS.

Hi [@Gualtier Malde](https://developer.apple.com/forums/profile/Gualtier Malde) , thanks for clarifying.

Does that mean that there is no way one can access the IOBluetooth framework before some user logs in? Are there any alternatives for accessing Bluetooth settings programmatically on system startup (before user login)?

To give a bit of context, I built myself a handy command line tool for personal use that uses the IOBluetooth framework to ensure that my keyboard and trackpad are connected. I then created a simple launch daemon plist to run this tool on system boot. This worked flawlessly on Ventura, but stopped working on Sonoma. I tried adding the tool as well as the launchd binary to TCC manually by dragging them into the Privacy and Security -> Bluetooth settings window, but this doesn't seem to help.

Thanks!

Hi Gualtier Malde, thank for confirming my findings. It seems strange that you can't approve BT for an app using an MDM as you can for a users Desktop/Documents/Downloads folder. Is this something intentional or is it going to b implemented as part MDM Privacy Preferences payload to grand BT access for system apps/daemons?

Thanks

Hi @Gualtier Malde, any updates on this?

Thanks!

IOBluetooth API is broken in more than one way, as others noted:

  1. Daemons cannot access IOBluetooth anymore.
  2. An application has no way to detect this situation. API returns an empty array if there are no Bluetooth devices connected or if access is not granted. No errors. Diagnostics is impossible.
  3. No MDM payload for allowing Bluetooth access. Not sure how it was planned to be done in an enterprise environment.