Core Bluetooth

RSS for tag

Communicate with Bluetooth 4.0 low energy devices using Core Bluetooth.

Posts under Core Bluetooth tag

200 Posts

Post

Replies

Boosts

Views

Activity

Use AccessorySetupKit for Accessory Authentication (BLE L2CAP)
PLATFORM AND VERSION iOS Development environment: Xcode Xcode 27.0, macOS macOS Golden Gate 27.0 Run-time configuration: iOS iOS 27.0 DESCRIPTION OF PROBLEM Environment: 1.I have a BLE hardware development board, The BLE broadcast name is "feature", Integrate an Apple Authentication 4.0 Coprocessor. The phone is iPhone 12 Pro Max, and the system is iOS 27 2.The source code of the app is from https://developer.apple.com/documentation/AccessorySetupKit/setting-up-and-authorizing-a-bluetooth-accessory. Modify the app's identifier from E56A082E-C49B-47CA-A2AB-389127B8ABE4 to F299FC19-5898-4F68-ACE6-E036ABE50781, that is Authenticated Accessory Capability Service of Accessory Authentication (BLE L2CAP). 3.descriptor.supportedOptions = [.bluetoothPairingLE, .bluetoothHID] Abnormal phenomenon: 1.ASKSample.app paired accessory name "feature" successful, but iPhone just connect accessory and read PSM characteristic every 10s, iPhone not send "LE Credit Based Connection Request - (PSM: 0x0080)". 2.I try set value of Authentication Channel PSM 7401DD11-3558-4459-98EE-371BBFC84C45 to [00, 80] or [80, 00], detailed packet capture of PacketLogger.app(from Additional_Tools_for_Xcode_27) is same, no "LE Credit Based Connection Request - (PSM: 0x0080)". 3.Detailed packet capture of Console.app will show error log "No authorized extension feature, missing services.txt". "NSInvalidArgumentException" is not report from my app. Question: 1."LE Credit Based Connection Request - (PSM: 0x0080)" is this automatically initiated by the iOS system? Is it necessary for the app to call the code peripheral.openL2CAPChannel(0x0080)? Does the app need to send RequestAuthSetup (0x5100)? 2.Is the code I provided sufficient to complete the testing of Accessory Authentication (BLE L2CAP) without any code modifications? Alternatively, could you provide a Demo app for me to test with Accessory Authentication (BLE L2CAP)? 3.The current Accessory Authentication (BLE L2CAP) testing process has not passed. I have provided two BLE packet captures and one iOS system packet capture to help identify where the problem lies. log: 1.search "No authorized extension feature, missing services" for error log. 2.20261014_Big-endian_parsing_PSM_Multiple_Read_PSM.pklg and No authorized extension feature, missing services.txt were captured simultaneously. The complete process from "October 14 10:49:10.631" to "October 14 10:49:11.723" in pklg includes connecting, reading PSM, and disconnecting. error flow of Console.app: ① DADaemonServer 错误 2026-10-14 10:49:11.243577 +0800 No authorized extension feature, missing services: DADevice: ID F202EAF6-578A-4F32-9FB9-668A12D3972F, name 'Blue Dice', Conn < Bluetooth >, btID 3d46f443-883a-ea17-3d63-ae00ec994cd4, btNm feature, flags AccessorySetup, BTPaired, type Hi-Fi Speaker, bluetoothSetupFinished yes, wifiAwareSetupInProgress yes, { DADeviceAppAccessInfo: com.example.apple-samplecode.ASKSample--SAMPLE-CODE-DISAMBIGUATOR-, ID F202EAF6-578A-4F32-9FB9-668A12D3972F, state Authorized, < Bluetooth >, Time 2026-10-14-02:48:46.371, disConfig asID 19D0C4AC-212F-4040-BA0A-EA8783422A0F, btSv [ BLE MFi ], com.example.apple-samplecode.ASKSample--SAMPLE-CODE-DISAMBIGUATOR-, flags 0x22 < BluetoothPairingLE BluetoothHID > } ② Server.LE 默认 2026-10-14 10:49:11.270649 +0800 Adding "needsMFiAuthentication4.0" tag to device "3D46F443-883A-EA17-3D63-AE00EC994CD4" ③ BTLEServer 调试 2026-10-14 10:49:11.282474 +0800 Received XPC message: <OS_xpc_dictionary: <dictionary: 0x7ba5048000> { count = 2, transaction: 1, voucher = 0x101282240, contents = "kMsgId" => <string: 0x7ba5019530> { string cache = 0x0, length = 16, contents = "MFiAccessoryAuth" } "kMsgArgs" => <dictionary: 0x7ba5039080> { count = 1, transaction: 0, voucher = 0x0, contents = "kPeerIdentifier" => <uuid: 0x7ba50194a0> 3D46F443-883A-EA17-3D63-AE00EC994CD4 } }> BTLEServer 默认 2026-10-14 10:49:11.282486 +0800 Performing MFI Auth for CBPeripheral UUID 3D46F443-883A-EA17-3D63-AE00EC994CD4 CoreBluetooth 调试 2026-10-14 10:49:11.282499 +0800 Sending synchronous XPC message CBMsgIdPeerHasTag: { kCBMsgArgDeviceUUID = "3D46F443-883A-EA17-3D63-AE00EC994CD4"; kCBMsgArgName = "needsMFiAuthentication4.0"; } ④ CBStackDeviceMonitor 默认 2026-10-14 10:49:11.375700 +0800 GATT device init completed: Device 3D46F443-883A-EA17-3D63-AE00EC994CD4 ⑤ CoreBluetooth 调试 2026-10-14 10:49:11.615127 +0800 Sending XPC message CBMsgIdServiceDiscoverCharacteristics: {kCBMsgArgDeviceUUID = "3D46F443-883A-EA17-3D63-AE00EC994CD4";kCBMsgArgServiceEndHandle = 48;kCBMsgArgServiceStartHandle = 46;kCBMsgArgUUIDs = ("MFi Team ID","MFi Protocol String","MFi Command","MFi Accessory Type","MFi Accessory Attributes","MFi Auth PSM");} ⑥ ASTCommon 信息 2026-10-14 10:49:11.707600 +0800 Reset -- (null) ASTCommon 调试 2026-10-14 10:49:11.707613 +0800 Removing devices: <NSIndexSet: 0xb0a5e8a79a88d37f>[number of indexes: 1 (in 1 ranges), indexes: (0)] ⑦ <缺少描述> 默认 2026-10-14 10:49:11.714044 +0800 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[1]' *** First throw call stack: (0x184183190 0x183f00380 0x1840fbd9c 0x18417b628 0x100881008 0x10086de44 0x100867e54 0x20abe45d4 0x20abe4670 0x20aba75ec 0x20ab70b10 0x20ab7d454 0x20ab71394 0x1b25dfccc 0x1b25f9fb4 0x1b25e887c 0x1b25e9470 0x1b25ef278 0x1b25ef044 0x1841347a0 0x18412588c 0x1841267f4 0x1845efda8 0x1847ea4d4 0x100858b38 0x183f775b8) ⑧ Packet Logging 调试 2026-10-14 10:49:11.714955 +0800 LOG; 22.612049; 24399DE4-4BCF-44C4-BFC8-3D7636310B99_81C912B0-C4BD-4090-A9A5-51F6034678DF; Bluetooth LE; Event; DETACH; GenericMFi detached! ⑨ Server.LE.Security 默认 2026-10-14 10:49:11.717602 +0800 Removing temporary security keys for device 3D46F443-883A-EA17-3D63-AE00EC994CD4 Server.LE.Security 默认 2026-10-14 10:49:11.727792 +0800 Removing temporary IRK for device 3D46F443-883A-EA17-3D63-AE00EC994CD4 STEPS TO REPRODUCE 1.open ASKSample.xcodeproj, run ASKSample.app on iPhone. 2.click "Add Dice" on app, app will find accessory name "feature", click "Set Up", Accessory Paired successful. SUPPORT INFORMATION Did someone from Apple ask you to submit a code-level support request? No Do you have a focused test project that demonstrates your issue? Yes, I have a focused test project to submit with my request What code level support issue are you having? Problems with an Apple framework API in my app NAME AND APPLE ID OF APP ASK Sample All log in attached file.
0
0
7
20m
CBPeer.identifier changes after OS update and device reboot on iOS 27 (non-bonded BLE peripheral)
Summary Our app uses CBPeer.identifier in Core Bluetooth to identify BLE peripherals. For the same non-bonded BLE peripheral, we have observed the following behavior: On iOS 18, CBPeer.identifier did not change across OS updates or device reboots. On devices updated to iOS 27.0, the CBPeer.identifier of the same peripheral became a different value after the OS update. On iOS 27.0, we have also confirmed that CBPeer.identifier changes after a device reboot. API documentation: https://developer.apple.com/documentation/corebluetooth/cbpeer/identifier We would like to confirm whether this is a specification change in iOS 27 and whether it is intended behavior. Questions Is it intended behavior in iOS 27 that CBPeer.identifier for a non-bonded BLE peripheral changes after an OS update or device reboot? If this is by design, is there any documentation (release notes, technical documents, API reference, etc.) that describes this change? Under what conditions can the CBPeer.identifier of a non-bonded BLE peripheral change? (e.g., OS update, device reboot, resetting Bluetooth settings, reinstalling the app, after a certain period of time, etc.) If we need to keep identifying the same non-bonded BLE peripheral across reboots and OS updates, what implementation approach do you recommend? Any information would be greatly appreciated. Thank you.
2
0
93
1h
WatchOS 27 throttles BLE discoveries
Hi! We have an app that highly depends on CoreBluetooth including scanning for peripherals with an advertised serviceUUID. Our app sets the CBCentralManagerScanOptionAllowDuplicatesKey flag to true while scanning. Receiving continuous discovery events about nearby devices is key to measure the RSSI before connecting. Updating some of our test devices to watchOS 27 we noticed that our app is broken. To analyze further we created a simple app to compare behavior between watchOS 26 and 27, and the difference is clear. On the 27 device it behaves like the flag is ignored and we only receive a couple of callbacks to centralManager(_:didDiscover:advertisementData:rssi:) then it stops. We could not find any documentation declaring this as a new restriction or something regarding that has changed. Is this a bug, or is there a way to get the old behavior on the new OS? The example app used for testing is available here: https://github.com/levente-gulyas-skidata/WatchBLEExperiments (Change the serviceUUID for testing if needed) Thank you, Levi
0
0
28
11h
M3 Max (BCM4388), macOS 15.6.1: A2DP to an SBC speaker shows 57% ReTx and constant packet drops; a non-Apple sender to the same speaker is clean (FB25169767)
I have a reproducible Bluetooth audio fault on my MacBook Pro M3 Max and have narrowed it down as far as I can from user space. I have filed it as FB25169767. I am posting the data here in case it helps others with the same log lines, and in case an Apple engineer can say what to capture next. I used AI tools for this investigation: Claude to run the tests and analyse the logs, and ChatGPT for web research. I did the listening tests myself, and the outside sources quoted below were checked against the originals. My setup MacBook Pro M3 Max (Mac15,9), macOS 15.6.1 (24G90) Bluetooth controller: Broadcom BCM4388, firmware 22.5.542.2788 Sink: Creative T100 desktop speaker, Bluetooth 5.0, A2DP, SBC only Negotiated: SBC 44.1 kHz joint stereo, bitpool 52, 322 kbps, 5 frames x 117 B per packet every 14.51 ms, L2CAP MTU 672 The speaker is about 25 cm from the Mac, with line of sight. Wi-Fi is on 5 GHz. A Magic Trackpad is connected. Symptom I have heard audible gaps from this speaker in every app for years. My AirPods and Sony WH-1000XM4 on the same Mac do not glitch. What bluetoothd reports for my speaker A2DP LinkQualityReport, one line a second while streaming: A2DP LinkQualityReport: Handle = 11 ReTx = 75.8% (135 / 178), NAK = 0, NoSync = 135, TxPwr = 7 dBm, RSSI = -46, {50,75,90}th Noise = {-102,-102,-101} for 29 ch, 2EDR pkts = 138, 3EDRTx pkts = 0, HDR4Tx pkts = 0, HDR8Tx pkts = 0, ... CoexDenial = 0, CoexRequest = 0, ... TxFlush pkts = 0, Tx2Flush pkts = 0, rate = 322 kbps Flow off = 0 Over 11,808 reports from my normal use (3.3 h of streaming, 12 to 13 October 2026): Speaker (SBC) AirPods (AAC), earlier capture ReTx median 56.6% (p10 50.5%, p90 63.0%) median 8.1% Retransmission cause all NoSync, NAK 0 mostly NoSync RSSI median -38 dBm about -47 dBm Noise about -100 dBm similar Packets on air about 195/s, all 2-EDR (about 2.8 attempts per 14.51 ms audio packet) about 38/s, mostly HDR TxPwr, AFH channels 7-8 dBm, about 44 8 dBm, about 45 "Link Adaptive Packet type support" 0 1 Packet drops 17.6 a minute (25.8 a minute on another day) 0 while streaming This is what the drops look like in my log: [Server.A2DP] A2DP packet flushed: L2CAP (chip) flush occured. Current sequence=28, timestamp=40557459 [Stack.L2CAP] Write in progress (status=65535) [Server.A2DP] A2DP packet flushed: Audio Queue full, remove oldest and insert sequence=29 (latest), timestamp=40557479 Every one of the 2,670 "Audio Queue full" drops in that period comes with an L2CAP "Write in progress (status=65535)" on the same thread in the same millisecond, just before it. The other 795 drops are "L2CAP (chip) flush occured". So most of the lost audio is discarded on the host when the previous write to the controller has not completed yet. Other details: The report's TxFlush pkts, Tx2Flush pkts and slot counters are 0 in every report for this link, also in seconds with a logged chip flush. Flow off is above 0 in only 19 of 2,835 seconds (one capture), so the controller's ACL buffers are not usually full. bluetoothd logs "Setting flush timeout, chipId:23" and "Dynamic Latency settting flush timeout to 200 ms" at AirPods events, never at this speaker's stream start. Audio Timesync for this link: "Audio Delivery Average Time" 9750 to 16750, "Pending Packets" 18 to 27, "Queue depth" up to 8. Second symptom: CoreAudio overloads With this speaker, bluetoothd logs Initiate Audio Delivery Speed Change (0.9x or 1.1x) about once a second. With AirPods it happens only at stream start. Each change shifts the HAL clock: safety_violation_time_gap median 7.9 ms, max 20.9 ms (1,645 reports). Any client with a 256-frame IO buffer (Chrome Web Audio uses 256 below 96 kHz) then logs HALS_OverloadMessage: Overload possibly due to safety violation 50 to 100 times a minute. I ran a silent test: a CoreAudio client playing digital zeros to the speaker, 40 s per buffer size. HAL buffer Overloads/min ReTx 256 frames 49.5 60.5% 512 frames 0 58.0% 1024 frames 0 58.0% A bigger buffer stops the overloads but not the packet drops. Control experiment: a non-Apple sender to the same speaker I plugged a USB Bluetooth 4.0 dongle (Broadcom BCM20702A0) into the same Mac. macOS attaches no Bluetooth driver to it, so I could drive it from user space with BTstack (port/libusb, a2dp_source_demo). Same desk, same distance, same SBC bitpool 52 at 14.51 ms intervals. 2 min 24 s of audio, and I listened to all of it: 9,892 of 9,892 media packets completed, no flush, no audible gap. Packets in flight: median 2, max 5. Send to Number Of Completed Packets: median 27 ms, p95 48 ms, under 70 ms in steady state. BTstack sets no automatic flush timeout and never discards late packets. So my speaker's receiver and my room are fine. The fault is in Apple's transmit path for this link: bluetoothd, the BCM4388 firmware, or the link policy between them. This test cannot say which. What I ruled out Nothing I changed moved ReTx from 50 to 60%, and it does not follow RSSI between -36 and -56 dBm. Bluetooth off/on (ReTx 57.8% before, 58.8% after), re-pairing (64% after) Trackpad traffic (0 reports/s, ReTx 56%), Wi-Fi coexistence (5 GHz, CoexDenial 0) Lid open, nearby LED lamps unplugged, monitor USB-C cable unplugged, Mac moved 2 m away Audio content: digital silence behaves the same as music I have not yet tried a fresh boot (the Mac had been up 116 days), macOS 15.8.1 or a PacketLogger capture. Related Asahi Linux found that Apple's Broadcom controllers (BCM4377/4378/4388) need vendor command 0xFC57 (ACL priority) for clean A2DP, and that the whole audio connection must stay high priority while it carries audio: one low-priority packet, such as a volume change, causes a dropout (netdev list, 15 April 2026, "[PATCH v2] Bluetooth: Add Broadcom channel priority commands"). An earlier capture showed macOS sending 0xFC57 plus vendor commands 0x1DD, 0x205 and 0x22D per connection at playback start. A similar write-up with the same three log lines, ReTx 51.4% at -36 dBm, but triggered by sleep/wake and cured by Bluetooth off/on (which does not help me): https://note.com/honest_kudu5817/n/n7e8a12aecb13 Questions Does macOS apply a different link policy to a non-Apple SBC sink than to AirPods (ACL priority, automatic flush timeout, packet types, Dynamic Latency)? Does "Link Adaptive Packet type support=0" mean this link is excluded from something? Is 0xFC57 held for the whole stream, or dropped around AVRCP traffic such as volume changes? What does NoSync count exactly, and why would it be more than half of all transmissions at -40 dBm? Is there anything I can capture beyond PacketLogger with the Bluetooth logging profile that would help the Bluetooth team? Has anyone else seen "Write in progress (status=65535)" paired with "Audio Queue full" on a steady link like this, and found anything that changes it? I am happy to run more tests or share more logs.
0
0
36
2d
watchOS CoreBluetooth: BLE link stability, AutoReconnect and reduced reconnection range
I have a watchOS app communicating with a BLE peripheral during an active HKWorkoutSession. The workout provides sufficient runtime: once connected, the Watch can receive a notifying GATT characteristic approximately once per minute for hours, including while the display is off. In normal conditions the connection is very stable. The difficult case is outdoor use with marginal RF conditions. The peripheral and application protocol otherwise work reliably, but outdoors there are fewer reflected RF paths and normal body movement can intermittently obstruct the Watch-to-peripheral path. In those situations the link occasionally terminates with CBError.connectionTimeout. Reconnection is particularly important because this peripheral advertises for reconnection only approximately once per minute. We also know approximately which second of each minute the peripheral becomes active, so missing a single advertising opportunity can cause a relatively long data gap. I’m trying to better understand the supported CoreBluetooth/watchOS behavior in this situation. Maintaining a marginal existing connection Once the BLE connection is established, are there any public CoreBluetooth mechanisms or recommended practices for making that connection more robust against CBError.connectionTimeout? In particular, can application-level GATT activity have any influence on connection scheduling or link robustness, or is this entirely handled by the Bluetooth stack below CoreBluetooth? CBConnectPeripheralOptionEnableAutoReconnect with sparse advertising When CBConnectPeripheralOptionEnableAutoReconnect is enabled and the connection is lost, how does watchOS handle a peripheral that advertises only very infrequently? Does CoreBluetooth simply keep the reconnect pending and wait for subsequent advertisements indefinitely, subject to system policy? Known peripheral activity timing If the app knows approximately when the peripheral becomes active and advertises each minute, is there any supported way to make use of that timing during reconnection? Or should the app simply leave AutoReconnect pending and let CoreBluetooth handle reception? WWDC22 reduced reconnection range WWDC22 session 10135 says: “If your device is on the edge of Bluetooth range and repeatedly disconnects while in Background BLE connection, the reconnection range will be reduced. This means only devices close to the Apple Watch will reconnect.” The session also says these limits are counted over a rolling 24-hour window and are reset when the user interacts with the app. I would particularly appreciate clarification of how this works in practice: What conditions cause a disconnect to count toward this policy? Does this policy apply while an app has an active HKWorkoutSession and continues executing in the background? Is the state maintained per peripheral, per app, or more globally? What exactly constitutes the user interaction that resets it? Does bringing an already-running workout app back to the foreground reset it, or does the app need to be relaunched? Is there any public API or diagnostic indication that reduced reconnection range is currently active? Is there any supported way to explicitly clear/reset that state? Connection parameters Does watchOS expose any supported mechanism for a CoreBluetooth central to influence parameters relevant to connection robustness, such as connection interval, supervision timeout, PHY, transmit power, or similar link parameters? Diagnosing CBError.connectionTimeout When CoreBluetooth reports CBError.connectionTimeout, is there any supported diagnostic method to determine whether the Watch stopped receiving the peripheral, the peripheral stopped receiving the Watch, or whether this should simply be treated as a link-layer timeout without attribution to either side? For context, this is not primarily a background-runtime problem. The active workout keeps the app running and the normal persistent BLE connection can operate flawlessly for many hours. I’m specifically trying to understand the best supported strategy for preserving and recovering the BLE link when RF conditions temporarily become marginal, especially with a peripheral that advertises very sparsely after a disconnect. DTS asked me to post this question here for review.
3
2
286
6d
Bluetooth LE HID keyboard randomly disconnects after upgrading from macOS 26 to macOS 27
After upgrading my M1 MacBook Pro from macOS 26 to macOS 27, my NuPhy Kick75 Bluetooth keyboard started randomly disconnecting during normal use. This issue did not occur on macOS 26 with exactly the same Mac, keyboard, physical location, and usage environment. The problem started immediately after upgrading to macOS 27. The keyboard disconnects approximately 2–3 times per hour. When the interruption occurs, the Bluetooth connection indicator on the keyboard also shows that the Bluetooth link has been lost. This is therefore an actual Bluetooth disconnection rather than only input lag or delayed keyboard events. The keyboard automatically reconnects shortly afterward. macOS bluetoothd logs captured at the exact time of an occurrence confirm that the Bluetooth LE HID link is being disconnected. Hardware Mac: MacBook Pro with Apple M1 Keyboard: NuPhy Kick75 Bluetooth device name: Kick75 IO-2 Connection type: Bluetooth LE HID Regression macOS 26: No Bluetooth disconnections observed during long-term normal use. macOS 27: Random Bluetooth disconnect/reconnect events occur approximately 2–3 times per hour. No keyboard, firmware, physical location, or other hardware/environmental changes were made when the issue started. The behavioral change occurred immediately after upgrading the Mac from macOS 26 to macOS 27. Steps to Reproduce Connect a NuPhy Kick75 keyboard to an M1 MacBook Pro using Bluetooth. Use the keyboard normally for typing. Continue normal use for approximately one hour. At seemingly random intervals, keyboard input suddenly stops. At the same time, the keyboard's Bluetooth connection indicator shows that the Bluetooth link has been lost. macOS automatically reconnects to the keyboard shortly afterward. The same event can be observed in bluetoothd logs as an LE HID link disconnection. Frequency Intermittent but frequent. Approximately 2–3 occurrences per hour after upgrading to macOS 27. Expected Result The Bluetooth LE HID connection should remain stable during normal use, as it did on macOS 26. Actual Result The Bluetooth LE HID connection is unexpectedly terminated. macOS subsequently reconnects to the keyboard automatically. Relevant bluetoothd Log The following was captured during an actual disconnection at: 2026-09-15 17:47:44 Disconnect OI_HCI_LM_HANDLE: 0x55 (85) wakeUp: No RSSI: -37 -37 -37 -37 ... _GATT_LE_DisconnectedCB ... reason STATUS 708 LE Link disconnected ... reason 708 LE ConnManager disconnection complete reason 708 localRole=Central encrypted:1 linkReady:1 disconnectDevice:0 localRole:0 reason:708 result:307 Device disconnected - { devicename: Kick75 IO-2, result: 307 } App disconnected - { bundle: com.apple.BTLEServer, reconnecting: Y } macLeDeviceDisconnected: LE Connection disconnected. Device is a LE HID. BLE Disconnected Unspecified reason 708 Setting LeDevice to Compatible HID from Compatible HID The RSSI values immediately before the disconnection remained consistently around -37 dBm, indicating a very strong Bluetooth signal at the time the link was lost. The following fields appear consistently relevant to this event: reason:708 result:307 disconnectDevice:0 reconnecting:Y macOS also classified the keyboard as a Compatible HID. Related Community Reports This may not be isolated to the Kick75. There is an independent community report involving a NuPhy Air75 V3 on macOS 27 that describes very similar Bluetooth LE HID disconnections. That report has several notable similarities: The Air75 V3 disconnects repeatedly on macOS 27. The same keyboard reportedly operates normally on Windows and iOS 27. Other Bluetooth devices connected to the affected Mac reportedly remain stable. The reporter's macOS Bluetooth logs contain: Incompatible LE HID HID latency issue detected LE Link disconnected (reason 708) Another user reported the same problem with a NuPhy Air65 V3. NuPhy Support responded that they had adjusted Bluetooth parameters and optimized the Bluetooth connection interval, and offered a test firmware for further investigation. The original reporter later tested the same Air75 V3 over Bluetooth on a Mac running macOS 26 at an Apple Store and reported that it did not disconnect. The reporter also observed that having certain Apple Bluetooth HID devices connected at the same time could affect the frequency of the NuPhy disconnections. The community report is titled: “Air75 V3 randomly disconnects on macOS 27 Developer Beta (works perfectly on Windows & iOS 27)” I am including the link to that report with this feedback as supporting information. Importantly, that report involves different NuPhy hardware and a different Mac, but its LE Link disconnected (reason 708) log message closely matches the reason 708 observed independently on my Kick75. This suggests the issue may affect more than one NuPhy Bluetooth LE HID keyboard model under macOS 27. Summary My own reproducible observations are: Same M1 MacBook Pro Same NuPhy Kick75 Same physical environment Stable Bluetooth operation on macOS 26 Frequent disconnections immediately after upgrading to macOS 27 Approximately 2–3 disconnections per hour Keyboard Bluetooth indicator confirms actual link loss bluetoothd confirms an LE HID disconnection RSSI was approximately -37 dBm immediately before the disconnection macOS records reason 708, result 307, and subsequently attempts to reconnect An independent NuPhy Air75 V3 report on macOS 27 also contains LE Link disconnected (reason 708) Taken together, these observations suggest a possible Bluetooth LE HID compatibility regression introduced in macOS 27. I can provide additional Bluetooth diagnostics, a sysdiagnose, and reproduce the issue with Apple's Bluetooth debug logging profile enabled if required.
4
6
446
6d
Keeping a Local Wi-Fi TCP Transfer Alive in the Background Using Bluetooth Notifications — Is This Viable?
Requirement Description The app operates as a central device. It connects to a Bluetooth peripheral via Core Bluetooth. Once connected, the peripheral enables a Wi-Fi hotspot. The app joins this hotspot and transfers data over a TCP connection. The app needs to remain active in the background until this TCP data transfer is complete.  Question Regarding the Proposed Solution One proposed approach is to have the peripheral send periodic BLE notifications (reporting transfer progress) to the app, using each notification to briefly wake the app and extend its background execution time. Would this method successfully keep the TCP connection alive in the background until the transfer finishes? Does it comply with App Store review guidelines?  Request for Alternative Solutions If this approach is not viable, could you advise on any supported mechanisms or recommended architectures that would allow a local Wi-Fi TCP data transfer to complete reliably after the app moves to the background?
1
0
95
6d
Bluetooth Low Energy (BLE) 5 Extended Advertising
Hello, I’m currently working on a project that implements Bluetooth Low Energy (BLE) 5 Extended Advertising. We are experiencing an issue specifically on iOS 18.6.2. The device is visible/scannable, but we are unable to establish a connection with it. Initially, our advertising interval was set to 2 seconds. We suspected that this interval might be too long for reliable discovery on iOS, so we reduced it to 100 ms. With the same firmware and advertising configuration: iOS 26.5.2: the device is discovered and a connection can be established successfully. iOS 18.6.2: the device can be detected/scanned, but the connection cannot be established. Could you please clarify whether there are any known limitations, restrictions, or differences in the handling of Bluetooth 5 Extended Advertising between iOS 18.6.2 and newer iOS versions? In particular, we would like to know whether iOS 18.6.2 has any specific requirements regarding: BLE Extended Advertising / LE Extended Advertising Primary and secondary advertising channels Advertising intervals PHY configuration (1M / 2M / Coded PHY) Connectable Extended Advertising We would also appreciate any documentation or known issues related to Extended Advertising on iOS that could explain why the same device and configuration works correctly on iOS 26.5.2. Thank you in advance for your help.
1
0
211
2w
macOS CoreBluetooth peripheral: duplicate Device Information services and iOS gamepad recognition
I’m developing a macOS app that reads a wired controller and publishes a generic BLE HID gamepad for an iPhone. BLE communication works, but iOS does not expose the device through GameController. I’m looking for guidance on supported device-identity publication and controller-admission requirements. Environment Apple Silicon MacBookPro17,1: macOS 27.0, build 26A428 iPhone 15 Pro Max: iOS 27.0, build 24A437 Xcode 27 Peripheral implemented using CBPeripheralManager What works The iPhone can connect, perform dynamic characteristic reads, and read encryption-required characteristics using the retained pairing. It discovers the application’s HID service and reads its Report Map, HID Information, Report Reference, and Input Report. The descriptor in the iPhone’s system HID record matches the application’s remotely read report map byte-for-byte. The peripheral also receives an input subscription, although I cannot independently identify the subscribing consumer. What fails An independent GCController.controllers() observer remains empty. During the recorded HID initialization, the iPhone logs: Un-authenticated game controller device attached Start failed: 0xe00002bc IOHIDEventDriver start failed. For the same registry device, gamecontrollerd records: vendorID = 0 productID = 0 version = 0 manufacturer = 'Apple Inc.' product = '[Mac device name]' transport = 'BluetoothLowEnergy' I am not assuming that “Un-authenticated” identifies a specific authentication requirement. I would like to understand which supported admission requirement is unmet. Device Information observations The iPhone’s CoreBluetooth discovery exposes two distinct Device Information service instances: System service Observed UUID: 180A Manufacturer: Apple Inc. Model: MacBookPro17,1 No PnP characteristic exposed by successful all-characteristic discovery Application service Observed UUID: 0000180A-0000-1000-8000-00805F9B34FB Manufacturer: PS3 Bridge Model: BLE Gamepad Prototype PnP bytes: 02 00 00 01 00 00 01 The application publishes expanded Bluetooth-base UUIDs. I understand these represent the same assigned UUIDs; I am preserving the observed representations because I have not established whether every host component handles them identically. The application PnP value represents vendor-ID source 2, vendor 0, product 1, and version 0x0100. The system HID record therefore does not simply reflect that value unchanged. The duplicate-DIS layout also appears inconsistent with the unique primary DIS expected by HOGP. I have not established that this causes the driver rejection. Questions Is there a supported macOS API or architecture for publishing a coherent BLE HID device identity when macOS already exposes its own Device Information service? How does iOS select DIS/PnP information when constructing a system HID device in this arrangement? Is a generic BLE HID gamepad published through macOS CoreBluetooth a supported path to iOS GameController recognition? If so, what additional profile, identity, or authentication requirements apply? What supported diagnostics would distinguish an identity-selection problem from a separate controller-admission requirement? Available evidence I have diagnostic source, corrected per-service-instance inventories, and redacted phone logs available. I also have a small standalone CoreBluetooth publication reproducer. It is reduced and has not been validated as independently reproducing the full bridge’s controller rejection. A later connection-only observation reused an existing shared Bluetooth link and still showed zero controllers. I am not treating that as a fresh HID initialization or admission attempt. I’m seeking a supported implementation path without private APIs, Bluetooth daemon modifications, or changes to system security.
1
0
278
2w
macOS 26.7: opening Control Center Sound causes BLE HID mouse lag, HID service loss, and result 307
I am seeing a repeatable interaction between audio activity or audio-device discovery and a Bluetooth LE HID mouse on a Mac mini M2 Pro. Opening the detailed Sound panel in Control Center, or changing the HDMI audio output, makes the pointer stutter. Opening Apple’s Music.app has also caused a temporary complete loss of the mouse. In the worst cases, the mouse becomes completely unavailable and does not recover without Bluetooth troubleshooting or re-pairing. Configuration Mac mini Mac14,12, Apple M2 Pro, 32 GB RAM macOS Tahoe 26.7 (25G229) Also reproduced on macOS Tahoe 26.1 (25B78) Logitech MX Anywhere 3 Mac over Bluetooth LE VID 0x046D, PID 0xB025 Firmware MPM24.01_0015 Logitech MX Keys M Mac over Bluetooth LE PL4071UH display and audio output over HDMI Logi Options+ installed Trigger Connect the MX Anywhere 3 Mac and MX Keys over Bluetooth. Open Control Center from the menu bar. Open the detailed Sound panel, or change the HDMI audio output. Move the Bluetooth mouse continuously while audio-output discovery is taking place. The issue is intermittent, but it has been reproduced several times on both macOS 26.1 and 26.7. Pointer stuttering can continue after the Sound panel is closed. A later incident occurred when I opened Apple’s Music.app. The Bluetooth mouse became unavailable again, but this time it recovered automatically after approximately ten seconds. The Sony WH-1000XM6 headset was connected over Bluetooth, while the 512 GB USB flash drive was not connected. This shows that the USB drive is not required for a temporary mouse loss and makes concurrent Bluetooth audio activity a more relevant condition to investigate. The additional trigger suggests that the problem may not be limited to the Control Center interface itself and may also be associated with audio-subsystem initialization or audio-device activity. This is an observation, not yet a confirmed causal link. Additional condition in the permanent-loss cases In every incident where the mouse did not recover on its own and became effectively unusable, the following two devices were also present: a Sony WH-1000XM6 wireless headset connected over Bluetooth; a 512 GB SanDisk USB flash drive connected to the Mac. I am reporting this as a correlation, not as a confirmed cause. The headset adds simultaneous Bluetooth audio activity. The USB drive may or may not be relevant depending on its USB mode, activity, shielding, physical location, and possible 2.4 GHz interference. The 512 GB capacity is included only to identify the device. Less severe cursor stuttering has also been observed around Sound-panel discovery; the two devices above are specifically the common condition I recorded during the permanent mouse-loss incidents. Observed result The pointer starts stuttering and raw mouse HID reports develop multi-second gaps. In severe incidents, the Bluetooth mouse stops working entirely. Opening Music.app has also caused a temporary complete loss of the mouse; during that incident the Sony WH-1000XM6 was connected over Bluetooth, the USB flash drive was not connected, and the mouse recovered automatically after approximately ten seconds. Logi Options+ then displays the mouse as inactive. The mouse disappears from the IOHID tree, while the Bluetooth keyboard can remain present. A wired USB mouse remains responsive, so the Mac and pointer rendering are not completely frozen. The failure can persist after the Sound panel is closed. Relevant logs On macOS 26.7, bluetoothd repeatedly recorded the following sequence for the MX Anywhere 3 Mac: MX Anywhere 3 Mac needs low latency current connection parameters: interval 30.00 ms, latency 0 connection changed to: interval 7.50 ms, latency 44 Device "MX Anywhere 3 Mac" is Incompatible LE HID Device "MX Anywhere 3 Mac" does not have _HID_SERVICE_ Connection timed out disconnect result: 307 BLEPaired HIDBadBehavior Central The sequence repeated during automatic reconnection attempts. The mouse later recovered on some occasions, but other incidents required turning Bluetooth off for about 15 seconds, turning it back on, forgetting the mouse, and pairing it again. Instrumented reproduction During a monitored reproduction on macOS 26.1: detailed audio discovery started at +21.333 s; a 2.400 s gap in raw HID reports from the mouse occurred 0.899 s before that event; bluetoothd then reported a HID lag issue for VID 0x046D, PID 0xB025 at +1.897 s; no display-frame gaps were detected; there was no sustained CPU saturation. This indicates that the interruption is already present in the raw HID input stream. It does not appear to be only a cursor animation or WindowServer rendering delay. Expected result Discovering or switching audio outputs should not alter a separate BLE HID mouse connection, cause multi-second HID report gaps, remove _HID_SERVICE_, or disconnect the mouse. Technical points for investigation Could this be a macOS Bluetooth/HID connection-parameter or service-discovery problem triggered by concurrent audio discovery? In particular, why does macOS change the mouse from 30 ms / latency 0 to 7.5 ms / latency 44, then classify it as Incompatible LE HID, lose _HID_SERVICE_, and eventually disconnect it with result 307? Has anyone reproduced the same sequence with a Logitech BLE mouse, a Bluetooth audio headset, or a USB 3 storage device connected? The issue was also submitted through Apple’s public macOS feedback form on 24 September 2026. That form confirmed receipt but did not provide an FB case number. Possibly related report Another Developer Forums report describes a different BLE HID device with Incompatible LE HID and disconnect result 307 on macOS 27. The hardware and trigger are different, but the Bluetooth/HID failure signature may be related: https://developer.apple.com/forums/thread/845857
6
0
415
2w
CoreBluetooth reconnection to legacy BLE directed advertisements differs across iPad hardware
To whomever this may concern, We are investigating a BLE firmware-update compatibility issue affecting a legacy Nordic nRF51 DFU bootloader on a subset of iPads. We are seeking guidance on whether there are known CoreBluetooth or Bluetooth-controller differences across recent iPad hardware that could affect reconnection to Bluetooth LE connectable directed advertisements. Background Our accessory uses a legacy Nordic nRF51 DFU flow: The iPad is connected to the accessory’s normal application firmware. The app requests entry into DFU mode. The accessory disconnects normally. The accessory restarts into its bootloader. The bootloader sends connectable directed advertisements targeted at the iPad that initiated DFU. The iPad is expected to reconnect, after which the firmware transfer begins. Observed behavior On working iPads, the BLE trace shows: Application disconnect → accessory begins connectable directed advertising → iPad sends BLE connection indication → bootloader connection succeeds → DFU begins On affected iPads, the trace shows: Application disconnect → accessory begins the same connectable directed advertising → no connection indication from the iPad → DFU cannot proceed The accessory is advertising to the current resolvable address of the connected iPad. The bootloader starts directed advertising at nearly identical timing in both working and failing traces, approximately 456 ms after disconnect. The initial disconnect is normal in both cases: LL_TERMINATE_IND / Remote User Terminated Connection / reason 0x13 The problem occurs only after the accessory begins directed advertising. It seems like the iPad might be able to receive and listen to directed advertisement, however it seems to be unable to send back a connection indication. Hardware correlation observed so far We observed a correlation with Bluetooth controller vendor information visible in our BLE captures: FORMAT FOR FOLLOWING LINES Result -> Example device -> Observed controller vendor DFU succeeds -> iPad Air, 5th generation -> Broadcom DFU succeeds -> Other tested iPads, including one iPad with an A16-class platform -> Broadcom DFU fails -> One affected iPad with an A16-class platform -> MediaTek We want to be careful not to overstate this result: We have tested only one affected MediaTek-based iPad so far. The model string is MD3Y4LL/A and its current iOS version 26.6.1. The functioning Broadcomm iPads A16 we have tested that did not fail DFU process have model string MD7F4KN/A. The other iPad models we tested DFU on (which were all successful, albeit none of them were MediaTek chips, they were all Broadcomm) were: MRJN2KN/A, MM9C3KN/A, MQ6J3KN/A, MM6T3KN/A (the latter with iOS 26.6.1 as well, suggesting it is not necessarily an iPad OS version issue) We have not found a second MediaTek-based iPad to determine whether the behavior reproduces across that hardware. We initially suspected that recent non-cellular iPads might consistently use MediaTek, but this was disproved by the iPad Air, 5th generation we tested (MM9C3KN/A): it had no cellular connection and used Broadcom, and DFU worked normally. Therefore, we do not conclude that the issue is caused by MediaTek hardware. We only see a correlation worth investigating. What we have ruled out The target firmware image is not involved; failure occurs before any firmware data is transferred. The accessory reaches bootloader mode and sends directed advertisements at the expected time. The iOS Nordic DFU library already calls CoreBluetooth’s normal reconnect API: centralManager.connect(peripheral, options: nil) iOS does not expose an API allowing an app to create or send a raw Link Layer CONNECT_IND; therefore the application cannot directly work around controller-level connection behavior. The affected iPad does not provide a normal scanner/discovery callback for this directed bootloader advertisement, so matching by name or service UUID is not available as an application-layer workaround. Questions . Are there known CoreBluetooth, iPadOS, or Bluetooth-controller differences that can affect handling of BLE connectable directed advertisements, particularly when an accessory directs advertisements to a central using a resolvable private address? . Is there a recommended CoreBluetooth pattern for reconnecting to a known peripheral after it restarts into a legacy bootloader that uses directed advertising? . Does CBCentralManager.connect(_:options:) queue a pending connection request that should be serviced when a matching directed advertisement is received? If so, are there circumstances in which this behavior differs by iPad hardware or controller implementation? . Is there any public diagnostic information, entitlement, or supported API that could help us determine why a pending CoreBluetooth connection request does not result in a connection attempt in this scenario? . Does Apple recommend a specific compatibility approach for legacy BLE DFU bootloaders that use directed advertising, beyond updating the accessory firmware to use ordinary undirected advertising? . We can provide packet captures from both the working and failing cases, including timestamps, directed-advertisement target addresses, and the absence/presence of the subsequent connection indication. Thank you for any guidance on whether this is expected behavior, a known compatibility limitation, or if there is anything we could try on our end to hopefully resolve this issue.
1
0
289
2w
macOS grants half the connection-event airtime that iOS does, for the same accessory
We make a BLE peripheral that streams continuously. It's been running against Android, Windows, macOS and iOS for years. Android and Windows sit at ~1000 kbps and stay there — many host devices, many OS versions, no per-host tuning. macOS and iOS give us about half that. We've sniffed the BLE link using a Bluetooth sniffer to find out where it goes. Same board, same firmware, every session. Read off the air trace, not from host APIs: 2M PHY both directions (LL_PHY_UPDATE_IND 0x02 / 0x02) DLE max_tx_octets = 251 ATT MTU 247 15.00 ms interval, peripheral latency 0 no encryption no other BLE or BT Classic connections active during the session (all other devices removed and forgotten) WiFi turned off for around half of the sessions, didn't seem to make any difference Peripheral airtime per connection event: central airtime/event duty @ 15 ms throughput Android 11.14 ms 74% 995 kbps, sustained Windows ≥10.70 ms ≥71% ~1000 kbps, sustained macOS 6.96 ms 46% 561 kbps iOS 6.96 ms typical 46% ~560–600 kbps macOS comes out median 6.96, p90 6.96, max 7.09 across a whole session. Same number every time. iOS normally sits in the same place, with occasional brief excursions up to Android-like performance before dropping back down. Those excursions are worth describing, because they're the interesting part. In a handful of sessions out of many, iOS runs at 12.53 ms, 84% duty, ~1030 kbps. It never holds. It drops back inside 150 ms, with no renegotiation, no parameter change and no channel-map change anywhere in the trace. Sometimes it parks at 8.35 ms for ten seconds before moving again. This isn't us saying iOS is fine in practice — it clearly isn't, we can't ship against it. The point is that the radio and the stack demonstrably can fill a 12.53 ms event when they're allowed to, so whatever is holding them to 6.96 ms isn't a hardware ceiling. "It's a factor of ability" doesn't fit. This has been asked before and answered. In thread 774487, asked directly whether iOS limits packets per connection event to 4: "there is no 'limiting' going on as it is commonly understood ... We find that 4 is a more commonly true number than 6 or more some chipsets claim." In thread 770717, to a developer on iOS 18.2 running the same parameters we are: "iOS does not 'limit' the number of writes. It is just a factor of ability." Both answers need the accessory to be the variable. Ours isn't — same board, same firmware, minutes apart, and two non-Apple hosts take it to 1000 kbps and hold it indefinitely. The only thing that changes is which OS is acting as central. We don't think this can be explained by chipset capability when the chipset is the one thing held constant. It's airtime, not packet count. The "4 packets per connection event" number people quote here is the wrong unit, and we think that's why these threads go nowhere. Within one regime, as PDUs per event go up, PDU size goes down and the airtime doesn't move: iOS 9 PDUs @ 250.4 B -> 12.51 ms 10 PDUs @ 211.1 B -> 12.32 ms 11 PDUs @ 186.4 B -> 12.47 ms macOS 5 PDUs @ 239.4 B -> 6.73 ms 6 PDUs @ 178.1 B -> 6.60 ms Nothing is counting packets. The event closes on a clock. Count and airtime were the same measurement back when everything was 1M PHY and 27-byte PDUs — with 2M and DLE they aren't, and quoting a packet count now hides the mechanism instead of describing it. The peripheral isn't the limiter. The MD bit was set on the peripheral's last PDU in 2147 of 2148 connection events. It always had more data queued, and the central closed the event anyway. This isn't a new report. The same mechanism has been described here before. Thread 133092 (2019) reports macOS closing the connection event while the peripheral still has MD set — exactly what we measure. Thread 713349 reports "about 5 response packets per connection event," which is the same budget: 6.96 ms is 5 full-size PDUs. Thread 6025 reports a drop from 7 packets to 3. None of those received a reply. We're not raising them to relitigate old threads. The point is that three independent reports arriving at the same number across several years, on different accessories, points at a property of the scheduler rather than of anyone's hardware. On iOS, this looks like it changed in iOS 18. macOS has apparently behaved this way for years, going by the threads above. On iOS it's recent. We have video and screen recordings of this same peripheral tested on iOS 17, documented at the time as running consistently at around 1000 kbps. The behaviour described here started appearing when we moved to iOS 18. The firmware and the negotiated parameters are the same now as they were then, which points at a change in radio scheduling rather than anything on our side. What we're asking: Is the per-event airtime budget deliberate? ADG §55.6 and QA1931 cover interval, latency and timeout only. Neither mentions connection event length. Why do macOS and iOS give roughly half what Android and Windows give for the same accessory, and why can iOS reach 12.53 ms without staying there? Did anything change in iOS 18 around connection event scheduling? Is there anything we can do from the accessory or app side? We're already at 2M PHY, DLE 251, MTU 247 and the 15 ms floor. If the answer is "design for a floor, not a peak" — what's the floor? Right now we plan for ~560 kbps on Apple and roughly double that everywhere else, and that decides what we can ship, and whether we can count on Apple devices as a reliable platform for our product. Captures, recordings and analysis available if they're useful.
2
0
582
3w
BLE Channel Sounding: LL_CS_CONFIG_REQ rejected with Unsupported Feature Or Parameter Value
I'm testing Bluetooth Channel Sounding interoperability between an Apple device and a BLE peripheral. During Channel Sounding configuration, the peripheral sends an LL_CS_CONFIG_REQ, but the request is rejected by the central device with: LL_REJECT_EXT_IND Rejected Opcode: LL_CS_CONFIG_REQ Error Code: Unsupported Feature Or Parameter Value I would like to understand which parameter in the Channel Sounding configuration may be incompatible with the Apple device. Could the expert clarify which Channel Sounding configuration parameter would cause the Apple device to reject this LL_CS_CONFIG_REQ? if sniffer log is needed, I can send it via e-mail.
1
0
177
3w
AirPods Pro service visible in PacketLogger but absent from CoreBluetooth discovery
I’m investigating whether a consumer iPhone app can control AirPods Pro environmental listening settings using public APIs, while keeping all live audio processing inside the earbuds. On a real iPhone running iOS 26.6.1, with AirPods reporting model A3064 and firmware 8B41 in Settings: CoreBluetooth connects and successfully reads the manufacturer, model and firmware characteristics. Explicit discovery of service 7798082B-B7B7-45A6-9933-563492EFE04E returns no matching service. Unfiltered discovery completes without errors but also excludes that service. A system PacketLogger capture contains metadata mapping that service to handles 0x12–0x2B, and characteristic D5621CC1-F7AB-45DB-9403-9EAF744D5390 to value handle 0x18. System ATT reads of that handle receive responses. Our app performs no setting writes. We understand that system trace metadata does not establish third-party access. Is this service intentionally unavailable to third-party CoreBluetooth clients? Alternatively, is there a documented public connection, authorization or entitlement requirement that could explain its absence? If this service is unavailable, is there any supported API for controlling AirPods environmental amplification or frequency balance? A minimal Swift project and diagnostic report are available.
1
0
510
Sep ’26
Channel Sounding: supports(.channelSounding) is false on iPhone 17 Pro Max while Nearby Interaction reports the hardware as capable — what am I missing?
I'm trying to work out why Channel Sounding won't start on my device, and I'd be grateful for any pointers on what condition I haven't satisfied. What I see On an iPhone 17 Pro Max running iOS 27.0 beta (24A5390f), queried after the central manager reaches .poweredOn as the documentation requires: if #available(iOS 27.0, *) { print(CBCentralManager.supports(.channelSounding)) // false print(NISession.deviceCapabilities.supportsBluetoothChannelSounding) // true } No accessory or connection is involved — both are local queries. Because supports(.channelSounding) is false, the Core Bluetooth path fails with CBError code 13 ("Channel Sounding is not supported by the local or remote device"). I also tried calling startChannelSoundingSession(:) anyway, past my own capability check, against a connected peer; the same code 13 comes back from peripheral(:didCompleteChannelSoundingSession:), so it isn't merely an advisory check. The Nearby Interaction path gets further — its capability check passes, so session.run(_:) is called with NINearbyAccessoryConfiguration(bluetoothChannelSoundingIdentifier:previousBluetoothIdentifier:) against a paired, connected reflector — and then invalidates with NIErrorCodeSessionFailed (-5887). Same result with isCameraAssistanceEnabled set to both true and false. Apple's own "Measuring Distance Between Devices Using Channel Sounding" sample behaves identically on this device, so it isn't my code. What I've ruled out Querying before .poweredOn — the value is read in centralManagerDidUpdateState when the state is .poweredOn. Hardware — this is an iPhone 17 Pro Max, and Nearby Interaction's own capability check reports the hardware as capable. The Language & Region setting — changing it makes no difference. Beta staleness — updated across two betas, no change. The reflector — it implements the Ranging Service GATT server and the reflector role, and ranges successfully against another unit of its own model. What I'm unsure about The header comment for CBCentralManagerFeatureChannelSounding reads: The hardware and region supports channel sounding That's the only mention of "region" I can find in any Channel Sounding documentation — WWDC26 session 369 lists the N1 chip and the accessory-side requirements, but nothing about region, and there's no API to query that condition. My device is a South Korea market unit operating in South Korea, so I'm wondering whether that's what I'm hitting, but I have no way to confirm it. I'd also be glad to be told I'm simply wrong about something more mundane. Questions What conditions cause supports(.channelSounding) to return false on a device that has the N1 chip? Is region genuinely one of them, and if so, is it determined by the market the device was sold in, its current location, or something else? Should NISession.deviceCapabilities.supportsBluetoothChannelSounding be expected to agree with the Core Bluetooth check, or does it intentionally report hardware capability only? If the latter, is there a supported way to check Channel Sounding availability before running a session? For anyone with Channel Sounding working: which path are you using — Core Bluetooth's startChannelSoundingSession(_:), or NISession with NINearbyAccessoryConfiguration? And does supports(.channelSounding) return true for you? Question 3 is mostly to help me tell whether this is specific to my device. Thanks — happy to share more logs or a minimal reproducer if it's useful.
6
1
1.1k
Sep ’26
AccessorySetupKit connects and disconnects BLE accessory before .accessoryAdded when using .bluetoothPairingLE
I am using AccessorySetupKit on iOS 26 to set up a BLE accessory. My discovery descriptor includes .bluetoothPairingLE the bonding mechanism is LESC (Just Works without IO capability). let descriptor = ASDiscoveryDescriptor() descriptor.bluetoothServiceUUID = NordicServiceUUID.nus.toCBUUID() descriptor.supportedOptions = [.bluetoothPairingLE] My peripheral shows up in the picker and after selecting it ASK goes through a connection and disconnection cycle before calling .accessoryAdded event within my app. Logging on the peripheral side (nRF5 SDK 17) shows that the ASK picker connected, bonded successfully, and then triggered a remote terminated connection event (0x13). Prior implementation without .bluetoothPairingLE flag used did not disconnect from the peripheral before calling .accessoryAdded. The issue I found with this implementation is that the Pairing Modal would not always be presented and thus we are trying to leverage .bluetoothPairingLE flag for consistent behaviour across various iPhones / iOS combinations. My question, is it expected behaviour for AccessorySetupKit to connect, perform bonding, then disconnect from the peripheral prior to providing said accessory to the app via .accessoryAdded callback? I could find no documentation or community discussion discussing this behaviour or flow.
0
0
218
Sep ’26
IRK-resolvable BLE advertisements stops after screen turns off
Device and software: iPhone model: iPhone 15 Pro iOS 27 Public Beta 6 Build: 24A5430a BLE receivers: two independent ESP32's IRK has worked reliably on iOS 26 and past versions. Observed behavior: With the iPhone display on both BLE receivers detect advertisements that resolve correctly using the enrolled IRK. No more than 10 seconds after the display is turned off, the IRK-resolvable advertisements stop. The IRK identity returns immediately when a notification wakes the display or when I manually do. Bluetooth itself remains active while this happens. The receivers continue to see several strong advertisements from the phone with some unidentified rotating addresses. The unidentified addresses rotate periodically and cannot be associated with the enrolled IRK. Additional observations: When my Apple Watch is powered on and connected, the iPhone remains IRK-detectable while the screen is off. It stops again when watch is disconnected. Connecting Bluetooth headphones does not have the same effect. The IRK-resolvable advertisement stops even while music continues playing. Moving the affected phone between two receivers confirmed that the unidentified rotating advertisements physically followed the phone. The existing IRK remains valid because it resolves the phone again immediately whenever the display wakes. I couldnt find any intentional IRK, private-address or screen-off advertising change documented in the iOS 27 release notes or any discussions online. Has anyone else observed this on iOS 27?
0
0
238
Sep ’26
Peripheral reconnected while my app was force-quit and the app clearly ran. Is state restoration supposed to do that?
Central talking to one custom peripheral, CoreBluetooth state restoration enabled. Behavior I understand: iOS kills the app for memory pressure, peripheral does something, restoration relaunches into the background. Documented, and I have watched it work. Behavior I do not: I force-quit from the app switcher. The device had been unplugged and off for about a week. Plugged it back in and within a minute it had fresh data that only my app could have sent. So the app ran, and I never opened it. Everything I have read says force-quit is a hard opt-out until the user launches again. The only theory I have is that this is not the same event class as what I tested before. Earlier tests were all notifications from an already-connected peripheral. This time there was a connect request outstanding from before the force-quit, and it completed when the device came back. Possibly a pending connection completing is handled differently than traffic on a live link. I do not have instrumentation on this yet, so I cannot say whether it relaunched or was still resident, and I cannot rule out that the phone rebooted sometime during the week. Adding logging before I try to reproduce. Has anyone characterized this properly? Specifically whether a connectPeripheral pending from before a force-quit survives, and whether its completion can trigger relaunch. The docs do not draw that distinction.
1
0
292
Sep ’26
AccessorySetupKit: Combining Bluetooth and Wi‑Fi Aware PIN Pairing for a Dual-Transport Accessory
Dear Apple:I am developing an app and I would like to use Apple's AccessorySetupKit to complete the binding with an accessory. My accessory supports both Bluetooth and Wi-Fi Aware. I want to use AccessorySetupKit to complete both the Bluetooth pairing and the Wi-Fi Aware pairing with the accessory in one go. For Bluetooth, we also need to use the ANCS service, so the Bluetooth pairing requires a PIN code pop-up. However, we would like to skip this Bluetooth PIN code pairing, or combine it with the Wi-Fi Aware PIN code pairing into a single step. Is this possible under the current AccessorySetupKit framework? Because having the user confirm the PIN code twice does not seem like a great user experience. I would appreciate your help in answering this. Thank you.
0
0
340
Sep ’26
Use AccessorySetupKit for Accessory Authentication (BLE L2CAP)
PLATFORM AND VERSION iOS Development environment: Xcode Xcode 27.0, macOS macOS Golden Gate 27.0 Run-time configuration: iOS iOS 27.0 DESCRIPTION OF PROBLEM Environment: 1.I have a BLE hardware development board, The BLE broadcast name is "feature", Integrate an Apple Authentication 4.0 Coprocessor. The phone is iPhone 12 Pro Max, and the system is iOS 27 2.The source code of the app is from https://developer.apple.com/documentation/AccessorySetupKit/setting-up-and-authorizing-a-bluetooth-accessory. Modify the app's identifier from E56A082E-C49B-47CA-A2AB-389127B8ABE4 to F299FC19-5898-4F68-ACE6-E036ABE50781, that is Authenticated Accessory Capability Service of Accessory Authentication (BLE L2CAP). 3.descriptor.supportedOptions = [.bluetoothPairingLE, .bluetoothHID] Abnormal phenomenon: 1.ASKSample.app paired accessory name "feature" successful, but iPhone just connect accessory and read PSM characteristic every 10s, iPhone not send "LE Credit Based Connection Request - (PSM: 0x0080)". 2.I try set value of Authentication Channel PSM 7401DD11-3558-4459-98EE-371BBFC84C45 to [00, 80] or [80, 00], detailed packet capture of PacketLogger.app(from Additional_Tools_for_Xcode_27) is same, no "LE Credit Based Connection Request - (PSM: 0x0080)". 3.Detailed packet capture of Console.app will show error log "No authorized extension feature, missing services.txt". "NSInvalidArgumentException" is not report from my app. Question: 1."LE Credit Based Connection Request - (PSM: 0x0080)" is this automatically initiated by the iOS system? Is it necessary for the app to call the code peripheral.openL2CAPChannel(0x0080)? Does the app need to send RequestAuthSetup (0x5100)? 2.Is the code I provided sufficient to complete the testing of Accessory Authentication (BLE L2CAP) without any code modifications? Alternatively, could you provide a Demo app for me to test with Accessory Authentication (BLE L2CAP)? 3.The current Accessory Authentication (BLE L2CAP) testing process has not passed. I have provided two BLE packet captures and one iOS system packet capture to help identify where the problem lies. log: 1.search "No authorized extension feature, missing services" for error log. 2.20261014_Big-endian_parsing_PSM_Multiple_Read_PSM.pklg and No authorized extension feature, missing services.txt were captured simultaneously. The complete process from "October 14 10:49:10.631" to "October 14 10:49:11.723" in pklg includes connecting, reading PSM, and disconnecting. error flow of Console.app: ① DADaemonServer 错误 2026-10-14 10:49:11.243577 +0800 No authorized extension feature, missing services: DADevice: ID F202EAF6-578A-4F32-9FB9-668A12D3972F, name 'Blue Dice', Conn < Bluetooth >, btID 3d46f443-883a-ea17-3d63-ae00ec994cd4, btNm feature, flags AccessorySetup, BTPaired, type Hi-Fi Speaker, bluetoothSetupFinished yes, wifiAwareSetupInProgress yes, { DADeviceAppAccessInfo: com.example.apple-samplecode.ASKSample--SAMPLE-CODE-DISAMBIGUATOR-, ID F202EAF6-578A-4F32-9FB9-668A12D3972F, state Authorized, < Bluetooth >, Time 2026-10-14-02:48:46.371, disConfig asID 19D0C4AC-212F-4040-BA0A-EA8783422A0F, btSv [ BLE MFi ], com.example.apple-samplecode.ASKSample--SAMPLE-CODE-DISAMBIGUATOR-, flags 0x22 < BluetoothPairingLE BluetoothHID > } ② Server.LE 默认 2026-10-14 10:49:11.270649 +0800 Adding "needsMFiAuthentication4.0" tag to device "3D46F443-883A-EA17-3D63-AE00EC994CD4" ③ BTLEServer 调试 2026-10-14 10:49:11.282474 +0800 Received XPC message: <OS_xpc_dictionary: <dictionary: 0x7ba5048000> { count = 2, transaction: 1, voucher = 0x101282240, contents = "kMsgId" => <string: 0x7ba5019530> { string cache = 0x0, length = 16, contents = "MFiAccessoryAuth" } "kMsgArgs" => <dictionary: 0x7ba5039080> { count = 1, transaction: 0, voucher = 0x0, contents = "kPeerIdentifier" => <uuid: 0x7ba50194a0> 3D46F443-883A-EA17-3D63-AE00EC994CD4 } }> BTLEServer 默认 2026-10-14 10:49:11.282486 +0800 Performing MFI Auth for CBPeripheral UUID 3D46F443-883A-EA17-3D63-AE00EC994CD4 CoreBluetooth 调试 2026-10-14 10:49:11.282499 +0800 Sending synchronous XPC message CBMsgIdPeerHasTag: { kCBMsgArgDeviceUUID = "3D46F443-883A-EA17-3D63-AE00EC994CD4"; kCBMsgArgName = "needsMFiAuthentication4.0"; } ④ CBStackDeviceMonitor 默认 2026-10-14 10:49:11.375700 +0800 GATT device init completed: Device 3D46F443-883A-EA17-3D63-AE00EC994CD4 ⑤ CoreBluetooth 调试 2026-10-14 10:49:11.615127 +0800 Sending XPC message CBMsgIdServiceDiscoverCharacteristics: {kCBMsgArgDeviceUUID = "3D46F443-883A-EA17-3D63-AE00EC994CD4";kCBMsgArgServiceEndHandle = 48;kCBMsgArgServiceStartHandle = 46;kCBMsgArgUUIDs = ("MFi Team ID","MFi Protocol String","MFi Command","MFi Accessory Type","MFi Accessory Attributes","MFi Auth PSM");} ⑥ ASTCommon 信息 2026-10-14 10:49:11.707600 +0800 Reset -- (null) ASTCommon 调试 2026-10-14 10:49:11.707613 +0800 Removing devices: <NSIndexSet: 0xb0a5e8a79a88d37f>[number of indexes: 1 (in 1 ranges), indexes: (0)] ⑦ <缺少描述> 默认 2026-10-14 10:49:11.714044 +0800 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[1]' *** First throw call stack: (0x184183190 0x183f00380 0x1840fbd9c 0x18417b628 0x100881008 0x10086de44 0x100867e54 0x20abe45d4 0x20abe4670 0x20aba75ec 0x20ab70b10 0x20ab7d454 0x20ab71394 0x1b25dfccc 0x1b25f9fb4 0x1b25e887c 0x1b25e9470 0x1b25ef278 0x1b25ef044 0x1841347a0 0x18412588c 0x1841267f4 0x1845efda8 0x1847ea4d4 0x100858b38 0x183f775b8) ⑧ Packet Logging 调试 2026-10-14 10:49:11.714955 +0800 LOG; 22.612049; 24399DE4-4BCF-44C4-BFC8-3D7636310B99_81C912B0-C4BD-4090-A9A5-51F6034678DF; Bluetooth LE; Event; DETACH; GenericMFi detached! ⑨ Server.LE.Security 默认 2026-10-14 10:49:11.717602 +0800 Removing temporary security keys for device 3D46F443-883A-EA17-3D63-AE00EC994CD4 Server.LE.Security 默认 2026-10-14 10:49:11.727792 +0800 Removing temporary IRK for device 3D46F443-883A-EA17-3D63-AE00EC994CD4 STEPS TO REPRODUCE 1.open ASKSample.xcodeproj, run ASKSample.app on iPhone. 2.click "Add Dice" on app, app will find accessory name "feature", click "Set Up", Accessory Paired successful. SUPPORT INFORMATION Did someone from Apple ask you to submit a code-level support request? No Do you have a focused test project that demonstrates your issue? Yes, I have a focused test project to submit with my request What code level support issue are you having? Problems with an Apple framework API in my app NAME AND APPLE ID OF APP ASK Sample All log in attached file.
Replies
0
Boosts
0
Views
7
Activity
20m
CBPeer.identifier changes after OS update and device reboot on iOS 27 (non-bonded BLE peripheral)
Summary Our app uses CBPeer.identifier in Core Bluetooth to identify BLE peripherals. For the same non-bonded BLE peripheral, we have observed the following behavior: On iOS 18, CBPeer.identifier did not change across OS updates or device reboots. On devices updated to iOS 27.0, the CBPeer.identifier of the same peripheral became a different value after the OS update. On iOS 27.0, we have also confirmed that CBPeer.identifier changes after a device reboot. API documentation: https://developer.apple.com/documentation/corebluetooth/cbpeer/identifier We would like to confirm whether this is a specification change in iOS 27 and whether it is intended behavior. Questions Is it intended behavior in iOS 27 that CBPeer.identifier for a non-bonded BLE peripheral changes after an OS update or device reboot? If this is by design, is there any documentation (release notes, technical documents, API reference, etc.) that describes this change? Under what conditions can the CBPeer.identifier of a non-bonded BLE peripheral change? (e.g., OS update, device reboot, resetting Bluetooth settings, reinstalling the app, after a certain period of time, etc.) If we need to keep identifying the same non-bonded BLE peripheral across reboots and OS updates, what implementation approach do you recommend? Any information would be greatly appreciated. Thank you.
Replies
2
Boosts
0
Views
93
Activity
1h
WatchOS 27 throttles BLE discoveries
Hi! We have an app that highly depends on CoreBluetooth including scanning for peripherals with an advertised serviceUUID. Our app sets the CBCentralManagerScanOptionAllowDuplicatesKey flag to true while scanning. Receiving continuous discovery events about nearby devices is key to measure the RSSI before connecting. Updating some of our test devices to watchOS 27 we noticed that our app is broken. To analyze further we created a simple app to compare behavior between watchOS 26 and 27, and the difference is clear. On the 27 device it behaves like the flag is ignored and we only receive a couple of callbacks to centralManager(_:didDiscover:advertisementData:rssi:) then it stops. We could not find any documentation declaring this as a new restriction or something regarding that has changed. Is this a bug, or is there a way to get the old behavior on the new OS? The example app used for testing is available here: https://github.com/levente-gulyas-skidata/WatchBLEExperiments (Change the serviceUUID for testing if needed) Thank you, Levi
Replies
0
Boosts
0
Views
28
Activity
11h
M3 Max (BCM4388), macOS 15.6.1: A2DP to an SBC speaker shows 57% ReTx and constant packet drops; a non-Apple sender to the same speaker is clean (FB25169767)
I have a reproducible Bluetooth audio fault on my MacBook Pro M3 Max and have narrowed it down as far as I can from user space. I have filed it as FB25169767. I am posting the data here in case it helps others with the same log lines, and in case an Apple engineer can say what to capture next. I used AI tools for this investigation: Claude to run the tests and analyse the logs, and ChatGPT for web research. I did the listening tests myself, and the outside sources quoted below were checked against the originals. My setup MacBook Pro M3 Max (Mac15,9), macOS 15.6.1 (24G90) Bluetooth controller: Broadcom BCM4388, firmware 22.5.542.2788 Sink: Creative T100 desktop speaker, Bluetooth 5.0, A2DP, SBC only Negotiated: SBC 44.1 kHz joint stereo, bitpool 52, 322 kbps, 5 frames x 117 B per packet every 14.51 ms, L2CAP MTU 672 The speaker is about 25 cm from the Mac, with line of sight. Wi-Fi is on 5 GHz. A Magic Trackpad is connected. Symptom I have heard audible gaps from this speaker in every app for years. My AirPods and Sony WH-1000XM4 on the same Mac do not glitch. What bluetoothd reports for my speaker A2DP LinkQualityReport, one line a second while streaming: A2DP LinkQualityReport: Handle = 11 ReTx = 75.8% (135 / 178), NAK = 0, NoSync = 135, TxPwr = 7 dBm, RSSI = -46, {50,75,90}th Noise = {-102,-102,-101} for 29 ch, 2EDR pkts = 138, 3EDRTx pkts = 0, HDR4Tx pkts = 0, HDR8Tx pkts = 0, ... CoexDenial = 0, CoexRequest = 0, ... TxFlush pkts = 0, Tx2Flush pkts = 0, rate = 322 kbps Flow off = 0 Over 11,808 reports from my normal use (3.3 h of streaming, 12 to 13 October 2026): Speaker (SBC) AirPods (AAC), earlier capture ReTx median 56.6% (p10 50.5%, p90 63.0%) median 8.1% Retransmission cause all NoSync, NAK 0 mostly NoSync RSSI median -38 dBm about -47 dBm Noise about -100 dBm similar Packets on air about 195/s, all 2-EDR (about 2.8 attempts per 14.51 ms audio packet) about 38/s, mostly HDR TxPwr, AFH channels 7-8 dBm, about 44 8 dBm, about 45 "Link Adaptive Packet type support" 0 1 Packet drops 17.6 a minute (25.8 a minute on another day) 0 while streaming This is what the drops look like in my log: [Server.A2DP] A2DP packet flushed: L2CAP (chip) flush occured. Current sequence=28, timestamp=40557459 [Stack.L2CAP] Write in progress (status=65535) [Server.A2DP] A2DP packet flushed: Audio Queue full, remove oldest and insert sequence=29 (latest), timestamp=40557479 Every one of the 2,670 "Audio Queue full" drops in that period comes with an L2CAP "Write in progress (status=65535)" on the same thread in the same millisecond, just before it. The other 795 drops are "L2CAP (chip) flush occured". So most of the lost audio is discarded on the host when the previous write to the controller has not completed yet. Other details: The report's TxFlush pkts, Tx2Flush pkts and slot counters are 0 in every report for this link, also in seconds with a logged chip flush. Flow off is above 0 in only 19 of 2,835 seconds (one capture), so the controller's ACL buffers are not usually full. bluetoothd logs "Setting flush timeout, chipId:23" and "Dynamic Latency settting flush timeout to 200 ms" at AirPods events, never at this speaker's stream start. Audio Timesync for this link: "Audio Delivery Average Time" 9750 to 16750, "Pending Packets" 18 to 27, "Queue depth" up to 8. Second symptom: CoreAudio overloads With this speaker, bluetoothd logs Initiate Audio Delivery Speed Change (0.9x or 1.1x) about once a second. With AirPods it happens only at stream start. Each change shifts the HAL clock: safety_violation_time_gap median 7.9 ms, max 20.9 ms (1,645 reports). Any client with a 256-frame IO buffer (Chrome Web Audio uses 256 below 96 kHz) then logs HALS_OverloadMessage: Overload possibly due to safety violation 50 to 100 times a minute. I ran a silent test: a CoreAudio client playing digital zeros to the speaker, 40 s per buffer size. HAL buffer Overloads/min ReTx 256 frames 49.5 60.5% 512 frames 0 58.0% 1024 frames 0 58.0% A bigger buffer stops the overloads but not the packet drops. Control experiment: a non-Apple sender to the same speaker I plugged a USB Bluetooth 4.0 dongle (Broadcom BCM20702A0) into the same Mac. macOS attaches no Bluetooth driver to it, so I could drive it from user space with BTstack (port/libusb, a2dp_source_demo). Same desk, same distance, same SBC bitpool 52 at 14.51 ms intervals. 2 min 24 s of audio, and I listened to all of it: 9,892 of 9,892 media packets completed, no flush, no audible gap. Packets in flight: median 2, max 5. Send to Number Of Completed Packets: median 27 ms, p95 48 ms, under 70 ms in steady state. BTstack sets no automatic flush timeout and never discards late packets. So my speaker's receiver and my room are fine. The fault is in Apple's transmit path for this link: bluetoothd, the BCM4388 firmware, or the link policy between them. This test cannot say which. What I ruled out Nothing I changed moved ReTx from 50 to 60%, and it does not follow RSSI between -36 and -56 dBm. Bluetooth off/on (ReTx 57.8% before, 58.8% after), re-pairing (64% after) Trackpad traffic (0 reports/s, ReTx 56%), Wi-Fi coexistence (5 GHz, CoexDenial 0) Lid open, nearby LED lamps unplugged, monitor USB-C cable unplugged, Mac moved 2 m away Audio content: digital silence behaves the same as music I have not yet tried a fresh boot (the Mac had been up 116 days), macOS 15.8.1 or a PacketLogger capture. Related Asahi Linux found that Apple's Broadcom controllers (BCM4377/4378/4388) need vendor command 0xFC57 (ACL priority) for clean A2DP, and that the whole audio connection must stay high priority while it carries audio: one low-priority packet, such as a volume change, causes a dropout (netdev list, 15 April 2026, "[PATCH v2] Bluetooth: Add Broadcom channel priority commands"). An earlier capture showed macOS sending 0xFC57 plus vendor commands 0x1DD, 0x205 and 0x22D per connection at playback start. A similar write-up with the same three log lines, ReTx 51.4% at -36 dBm, but triggered by sleep/wake and cured by Bluetooth off/on (which does not help me): https://note.com/honest_kudu5817/n/n7e8a12aecb13 Questions Does macOS apply a different link policy to a non-Apple SBC sink than to AirPods (ACL priority, automatic flush timeout, packet types, Dynamic Latency)? Does "Link Adaptive Packet type support=0" mean this link is excluded from something? Is 0xFC57 held for the whole stream, or dropped around AVRCP traffic such as volume changes? What does NoSync count exactly, and why would it be more than half of all transmissions at -40 dBm? Is there anything I can capture beyond PacketLogger with the Bluetooth logging profile that would help the Bluetooth team? Has anyone else seen "Write in progress (status=65535)" paired with "Audio Queue full" on a steady link like this, and found anything that changes it? I am happy to run more tests or share more logs.
Replies
0
Boosts
0
Views
36
Activity
2d
watchOS CoreBluetooth: BLE link stability, AutoReconnect and reduced reconnection range
I have a watchOS app communicating with a BLE peripheral during an active HKWorkoutSession. The workout provides sufficient runtime: once connected, the Watch can receive a notifying GATT characteristic approximately once per minute for hours, including while the display is off. In normal conditions the connection is very stable. The difficult case is outdoor use with marginal RF conditions. The peripheral and application protocol otherwise work reliably, but outdoors there are fewer reflected RF paths and normal body movement can intermittently obstruct the Watch-to-peripheral path. In those situations the link occasionally terminates with CBError.connectionTimeout. Reconnection is particularly important because this peripheral advertises for reconnection only approximately once per minute. We also know approximately which second of each minute the peripheral becomes active, so missing a single advertising opportunity can cause a relatively long data gap. I’m trying to better understand the supported CoreBluetooth/watchOS behavior in this situation. Maintaining a marginal existing connection Once the BLE connection is established, are there any public CoreBluetooth mechanisms or recommended practices for making that connection more robust against CBError.connectionTimeout? In particular, can application-level GATT activity have any influence on connection scheduling or link robustness, or is this entirely handled by the Bluetooth stack below CoreBluetooth? CBConnectPeripheralOptionEnableAutoReconnect with sparse advertising When CBConnectPeripheralOptionEnableAutoReconnect is enabled and the connection is lost, how does watchOS handle a peripheral that advertises only very infrequently? Does CoreBluetooth simply keep the reconnect pending and wait for subsequent advertisements indefinitely, subject to system policy? Known peripheral activity timing If the app knows approximately when the peripheral becomes active and advertises each minute, is there any supported way to make use of that timing during reconnection? Or should the app simply leave AutoReconnect pending and let CoreBluetooth handle reception? WWDC22 reduced reconnection range WWDC22 session 10135 says: “If your device is on the edge of Bluetooth range and repeatedly disconnects while in Background BLE connection, the reconnection range will be reduced. This means only devices close to the Apple Watch will reconnect.” The session also says these limits are counted over a rolling 24-hour window and are reset when the user interacts with the app. I would particularly appreciate clarification of how this works in practice: What conditions cause a disconnect to count toward this policy? Does this policy apply while an app has an active HKWorkoutSession and continues executing in the background? Is the state maintained per peripheral, per app, or more globally? What exactly constitutes the user interaction that resets it? Does bringing an already-running workout app back to the foreground reset it, or does the app need to be relaunched? Is there any public API or diagnostic indication that reduced reconnection range is currently active? Is there any supported way to explicitly clear/reset that state? Connection parameters Does watchOS expose any supported mechanism for a CoreBluetooth central to influence parameters relevant to connection robustness, such as connection interval, supervision timeout, PHY, transmit power, or similar link parameters? Diagnosing CBError.connectionTimeout When CoreBluetooth reports CBError.connectionTimeout, is there any supported diagnostic method to determine whether the Watch stopped receiving the peripheral, the peripheral stopped receiving the Watch, or whether this should simply be treated as a link-layer timeout without attribution to either side? For context, this is not primarily a background-runtime problem. The active workout keeps the app running and the normal persistent BLE connection can operate flawlessly for many hours. I’m specifically trying to understand the best supported strategy for preserving and recovering the BLE link when RF conditions temporarily become marginal, especially with a peripheral that advertises very sparsely after a disconnect. DTS asked me to post this question here for review.
Replies
3
Boosts
2
Views
286
Activity
6d
Bluetooth LE HID keyboard randomly disconnects after upgrading from macOS 26 to macOS 27
After upgrading my M1 MacBook Pro from macOS 26 to macOS 27, my NuPhy Kick75 Bluetooth keyboard started randomly disconnecting during normal use. This issue did not occur on macOS 26 with exactly the same Mac, keyboard, physical location, and usage environment. The problem started immediately after upgrading to macOS 27. The keyboard disconnects approximately 2–3 times per hour. When the interruption occurs, the Bluetooth connection indicator on the keyboard also shows that the Bluetooth link has been lost. This is therefore an actual Bluetooth disconnection rather than only input lag or delayed keyboard events. The keyboard automatically reconnects shortly afterward. macOS bluetoothd logs captured at the exact time of an occurrence confirm that the Bluetooth LE HID link is being disconnected. Hardware Mac: MacBook Pro with Apple M1 Keyboard: NuPhy Kick75 Bluetooth device name: Kick75 IO-2 Connection type: Bluetooth LE HID Regression macOS 26: No Bluetooth disconnections observed during long-term normal use. macOS 27: Random Bluetooth disconnect/reconnect events occur approximately 2–3 times per hour. No keyboard, firmware, physical location, or other hardware/environmental changes were made when the issue started. The behavioral change occurred immediately after upgrading the Mac from macOS 26 to macOS 27. Steps to Reproduce Connect a NuPhy Kick75 keyboard to an M1 MacBook Pro using Bluetooth. Use the keyboard normally for typing. Continue normal use for approximately one hour. At seemingly random intervals, keyboard input suddenly stops. At the same time, the keyboard's Bluetooth connection indicator shows that the Bluetooth link has been lost. macOS automatically reconnects to the keyboard shortly afterward. The same event can be observed in bluetoothd logs as an LE HID link disconnection. Frequency Intermittent but frequent. Approximately 2–3 occurrences per hour after upgrading to macOS 27. Expected Result The Bluetooth LE HID connection should remain stable during normal use, as it did on macOS 26. Actual Result The Bluetooth LE HID connection is unexpectedly terminated. macOS subsequently reconnects to the keyboard automatically. Relevant bluetoothd Log The following was captured during an actual disconnection at: 2026-09-15 17:47:44 Disconnect OI_HCI_LM_HANDLE: 0x55 (85) wakeUp: No RSSI: -37 -37 -37 -37 ... _GATT_LE_DisconnectedCB ... reason STATUS 708 LE Link disconnected ... reason 708 LE ConnManager disconnection complete reason 708 localRole=Central encrypted:1 linkReady:1 disconnectDevice:0 localRole:0 reason:708 result:307 Device disconnected - { devicename: Kick75 IO-2, result: 307 } App disconnected - { bundle: com.apple.BTLEServer, reconnecting: Y } macLeDeviceDisconnected: LE Connection disconnected. Device is a LE HID. BLE Disconnected Unspecified reason 708 Setting LeDevice to Compatible HID from Compatible HID The RSSI values immediately before the disconnection remained consistently around -37 dBm, indicating a very strong Bluetooth signal at the time the link was lost. The following fields appear consistently relevant to this event: reason:708 result:307 disconnectDevice:0 reconnecting:Y macOS also classified the keyboard as a Compatible HID. Related Community Reports This may not be isolated to the Kick75. There is an independent community report involving a NuPhy Air75 V3 on macOS 27 that describes very similar Bluetooth LE HID disconnections. That report has several notable similarities: The Air75 V3 disconnects repeatedly on macOS 27. The same keyboard reportedly operates normally on Windows and iOS 27. Other Bluetooth devices connected to the affected Mac reportedly remain stable. The reporter's macOS Bluetooth logs contain: Incompatible LE HID HID latency issue detected LE Link disconnected (reason 708) Another user reported the same problem with a NuPhy Air65 V3. NuPhy Support responded that they had adjusted Bluetooth parameters and optimized the Bluetooth connection interval, and offered a test firmware for further investigation. The original reporter later tested the same Air75 V3 over Bluetooth on a Mac running macOS 26 at an Apple Store and reported that it did not disconnect. The reporter also observed that having certain Apple Bluetooth HID devices connected at the same time could affect the frequency of the NuPhy disconnections. The community report is titled: “Air75 V3 randomly disconnects on macOS 27 Developer Beta (works perfectly on Windows & iOS 27)” I am including the link to that report with this feedback as supporting information. Importantly, that report involves different NuPhy hardware and a different Mac, but its LE Link disconnected (reason 708) log message closely matches the reason 708 observed independently on my Kick75. This suggests the issue may affect more than one NuPhy Bluetooth LE HID keyboard model under macOS 27. Summary My own reproducible observations are: Same M1 MacBook Pro Same NuPhy Kick75 Same physical environment Stable Bluetooth operation on macOS 26 Frequent disconnections immediately after upgrading to macOS 27 Approximately 2–3 disconnections per hour Keyboard Bluetooth indicator confirms actual link loss bluetoothd confirms an LE HID disconnection RSSI was approximately -37 dBm immediately before the disconnection macOS records reason 708, result 307, and subsequently attempts to reconnect An independent NuPhy Air75 V3 report on macOS 27 also contains LE Link disconnected (reason 708) Taken together, these observations suggest a possible Bluetooth LE HID compatibility regression introduced in macOS 27. I can provide additional Bluetooth diagnostics, a sysdiagnose, and reproduce the issue with Apple's Bluetooth debug logging profile enabled if required.
Replies
4
Boosts
6
Views
446
Activity
6d
Keeping a Local Wi-Fi TCP Transfer Alive in the Background Using Bluetooth Notifications — Is This Viable?
Requirement Description The app operates as a central device. It connects to a Bluetooth peripheral via Core Bluetooth. Once connected, the peripheral enables a Wi-Fi hotspot. The app joins this hotspot and transfers data over a TCP connection. The app needs to remain active in the background until this TCP data transfer is complete.  Question Regarding the Proposed Solution One proposed approach is to have the peripheral send periodic BLE notifications (reporting transfer progress) to the app, using each notification to briefly wake the app and extend its background execution time. Would this method successfully keep the TCP connection alive in the background until the transfer finishes? Does it comply with App Store review guidelines?  Request for Alternative Solutions If this approach is not viable, could you advise on any supported mechanisms or recommended architectures that would allow a local Wi-Fi TCP data transfer to complete reliably after the app moves to the background?
Replies
1
Boosts
0
Views
95
Activity
6d
Bluetooth Low Energy (BLE) 5 Extended Advertising
Hello, I’m currently working on a project that implements Bluetooth Low Energy (BLE) 5 Extended Advertising. We are experiencing an issue specifically on iOS 18.6.2. The device is visible/scannable, but we are unable to establish a connection with it. Initially, our advertising interval was set to 2 seconds. We suspected that this interval might be too long for reliable discovery on iOS, so we reduced it to 100 ms. With the same firmware and advertising configuration: iOS 26.5.2: the device is discovered and a connection can be established successfully. iOS 18.6.2: the device can be detected/scanned, but the connection cannot be established. Could you please clarify whether there are any known limitations, restrictions, or differences in the handling of Bluetooth 5 Extended Advertising between iOS 18.6.2 and newer iOS versions? In particular, we would like to know whether iOS 18.6.2 has any specific requirements regarding: BLE Extended Advertising / LE Extended Advertising Primary and secondary advertising channels Advertising intervals PHY configuration (1M / 2M / Coded PHY) Connectable Extended Advertising We would also appreciate any documentation or known issues related to Extended Advertising on iOS that could explain why the same device and configuration works correctly on iOS 26.5.2. Thank you in advance for your help.
Replies
1
Boosts
0
Views
211
Activity
2w
macOS CoreBluetooth peripheral: duplicate Device Information services and iOS gamepad recognition
I’m developing a macOS app that reads a wired controller and publishes a generic BLE HID gamepad for an iPhone. BLE communication works, but iOS does not expose the device through GameController. I’m looking for guidance on supported device-identity publication and controller-admission requirements. Environment Apple Silicon MacBookPro17,1: macOS 27.0, build 26A428 iPhone 15 Pro Max: iOS 27.0, build 24A437 Xcode 27 Peripheral implemented using CBPeripheralManager What works The iPhone can connect, perform dynamic characteristic reads, and read encryption-required characteristics using the retained pairing. It discovers the application’s HID service and reads its Report Map, HID Information, Report Reference, and Input Report. The descriptor in the iPhone’s system HID record matches the application’s remotely read report map byte-for-byte. The peripheral also receives an input subscription, although I cannot independently identify the subscribing consumer. What fails An independent GCController.controllers() observer remains empty. During the recorded HID initialization, the iPhone logs: Un-authenticated game controller device attached Start failed: 0xe00002bc IOHIDEventDriver start failed. For the same registry device, gamecontrollerd records: vendorID = 0 productID = 0 version = 0 manufacturer = 'Apple Inc.' product = '[Mac device name]' transport = 'BluetoothLowEnergy' I am not assuming that “Un-authenticated” identifies a specific authentication requirement. I would like to understand which supported admission requirement is unmet. Device Information observations The iPhone’s CoreBluetooth discovery exposes two distinct Device Information service instances: System service Observed UUID: 180A Manufacturer: Apple Inc. Model: MacBookPro17,1 No PnP characteristic exposed by successful all-characteristic discovery Application service Observed UUID: 0000180A-0000-1000-8000-00805F9B34FB Manufacturer: PS3 Bridge Model: BLE Gamepad Prototype PnP bytes: 02 00 00 01 00 00 01 The application publishes expanded Bluetooth-base UUIDs. I understand these represent the same assigned UUIDs; I am preserving the observed representations because I have not established whether every host component handles them identically. The application PnP value represents vendor-ID source 2, vendor 0, product 1, and version 0x0100. The system HID record therefore does not simply reflect that value unchanged. The duplicate-DIS layout also appears inconsistent with the unique primary DIS expected by HOGP. I have not established that this causes the driver rejection. Questions Is there a supported macOS API or architecture for publishing a coherent BLE HID device identity when macOS already exposes its own Device Information service? How does iOS select DIS/PnP information when constructing a system HID device in this arrangement? Is a generic BLE HID gamepad published through macOS CoreBluetooth a supported path to iOS GameController recognition? If so, what additional profile, identity, or authentication requirements apply? What supported diagnostics would distinguish an identity-selection problem from a separate controller-admission requirement? Available evidence I have diagnostic source, corrected per-service-instance inventories, and redacted phone logs available. I also have a small standalone CoreBluetooth publication reproducer. It is reduced and has not been validated as independently reproducing the full bridge’s controller rejection. A later connection-only observation reused an existing shared Bluetooth link and still showed zero controllers. I am not treating that as a fresh HID initialization or admission attempt. I’m seeking a supported implementation path without private APIs, Bluetooth daemon modifications, or changes to system security.
Replies
1
Boosts
0
Views
278
Activity
2w
macOS 26.7: opening Control Center Sound causes BLE HID mouse lag, HID service loss, and result 307
I am seeing a repeatable interaction between audio activity or audio-device discovery and a Bluetooth LE HID mouse on a Mac mini M2 Pro. Opening the detailed Sound panel in Control Center, or changing the HDMI audio output, makes the pointer stutter. Opening Apple’s Music.app has also caused a temporary complete loss of the mouse. In the worst cases, the mouse becomes completely unavailable and does not recover without Bluetooth troubleshooting or re-pairing. Configuration Mac mini Mac14,12, Apple M2 Pro, 32 GB RAM macOS Tahoe 26.7 (25G229) Also reproduced on macOS Tahoe 26.1 (25B78) Logitech MX Anywhere 3 Mac over Bluetooth LE VID 0x046D, PID 0xB025 Firmware MPM24.01_0015 Logitech MX Keys M Mac over Bluetooth LE PL4071UH display and audio output over HDMI Logi Options+ installed Trigger Connect the MX Anywhere 3 Mac and MX Keys over Bluetooth. Open Control Center from the menu bar. Open the detailed Sound panel, or change the HDMI audio output. Move the Bluetooth mouse continuously while audio-output discovery is taking place. The issue is intermittent, but it has been reproduced several times on both macOS 26.1 and 26.7. Pointer stuttering can continue after the Sound panel is closed. A later incident occurred when I opened Apple’s Music.app. The Bluetooth mouse became unavailable again, but this time it recovered automatically after approximately ten seconds. The Sony WH-1000XM6 headset was connected over Bluetooth, while the 512 GB USB flash drive was not connected. This shows that the USB drive is not required for a temporary mouse loss and makes concurrent Bluetooth audio activity a more relevant condition to investigate. The additional trigger suggests that the problem may not be limited to the Control Center interface itself and may also be associated with audio-subsystem initialization or audio-device activity. This is an observation, not yet a confirmed causal link. Additional condition in the permanent-loss cases In every incident where the mouse did not recover on its own and became effectively unusable, the following two devices were also present: a Sony WH-1000XM6 wireless headset connected over Bluetooth; a 512 GB SanDisk USB flash drive connected to the Mac. I am reporting this as a correlation, not as a confirmed cause. The headset adds simultaneous Bluetooth audio activity. The USB drive may or may not be relevant depending on its USB mode, activity, shielding, physical location, and possible 2.4 GHz interference. The 512 GB capacity is included only to identify the device. Less severe cursor stuttering has also been observed around Sound-panel discovery; the two devices above are specifically the common condition I recorded during the permanent mouse-loss incidents. Observed result The pointer starts stuttering and raw mouse HID reports develop multi-second gaps. In severe incidents, the Bluetooth mouse stops working entirely. Opening Music.app has also caused a temporary complete loss of the mouse; during that incident the Sony WH-1000XM6 was connected over Bluetooth, the USB flash drive was not connected, and the mouse recovered automatically after approximately ten seconds. Logi Options+ then displays the mouse as inactive. The mouse disappears from the IOHID tree, while the Bluetooth keyboard can remain present. A wired USB mouse remains responsive, so the Mac and pointer rendering are not completely frozen. The failure can persist after the Sound panel is closed. Relevant logs On macOS 26.7, bluetoothd repeatedly recorded the following sequence for the MX Anywhere 3 Mac: MX Anywhere 3 Mac needs low latency current connection parameters: interval 30.00 ms, latency 0 connection changed to: interval 7.50 ms, latency 44 Device "MX Anywhere 3 Mac" is Incompatible LE HID Device "MX Anywhere 3 Mac" does not have _HID_SERVICE_ Connection timed out disconnect result: 307 BLEPaired HIDBadBehavior Central The sequence repeated during automatic reconnection attempts. The mouse later recovered on some occasions, but other incidents required turning Bluetooth off for about 15 seconds, turning it back on, forgetting the mouse, and pairing it again. Instrumented reproduction During a monitored reproduction on macOS 26.1: detailed audio discovery started at +21.333 s; a 2.400 s gap in raw HID reports from the mouse occurred 0.899 s before that event; bluetoothd then reported a HID lag issue for VID 0x046D, PID 0xB025 at +1.897 s; no display-frame gaps were detected; there was no sustained CPU saturation. This indicates that the interruption is already present in the raw HID input stream. It does not appear to be only a cursor animation or WindowServer rendering delay. Expected result Discovering or switching audio outputs should not alter a separate BLE HID mouse connection, cause multi-second HID report gaps, remove _HID_SERVICE_, or disconnect the mouse. Technical points for investigation Could this be a macOS Bluetooth/HID connection-parameter or service-discovery problem triggered by concurrent audio discovery? In particular, why does macOS change the mouse from 30 ms / latency 0 to 7.5 ms / latency 44, then classify it as Incompatible LE HID, lose _HID_SERVICE_, and eventually disconnect it with result 307? Has anyone reproduced the same sequence with a Logitech BLE mouse, a Bluetooth audio headset, or a USB 3 storage device connected? The issue was also submitted through Apple’s public macOS feedback form on 24 September 2026. That form confirmed receipt but did not provide an FB case number. Possibly related report Another Developer Forums report describes a different BLE HID device with Incompatible LE HID and disconnect result 307 on macOS 27. The hardware and trigger are different, but the Bluetooth/HID failure signature may be related: https://developer.apple.com/forums/thread/845857
Replies
6
Boosts
0
Views
415
Activity
2w
CoreBluetooth reconnection to legacy BLE directed advertisements differs across iPad hardware
To whomever this may concern, We are investigating a BLE firmware-update compatibility issue affecting a legacy Nordic nRF51 DFU bootloader on a subset of iPads. We are seeking guidance on whether there are known CoreBluetooth or Bluetooth-controller differences across recent iPad hardware that could affect reconnection to Bluetooth LE connectable directed advertisements. Background Our accessory uses a legacy Nordic nRF51 DFU flow: The iPad is connected to the accessory’s normal application firmware. The app requests entry into DFU mode. The accessory disconnects normally. The accessory restarts into its bootloader. The bootloader sends connectable directed advertisements targeted at the iPad that initiated DFU. The iPad is expected to reconnect, after which the firmware transfer begins. Observed behavior On working iPads, the BLE trace shows: Application disconnect → accessory begins connectable directed advertising → iPad sends BLE connection indication → bootloader connection succeeds → DFU begins On affected iPads, the trace shows: Application disconnect → accessory begins the same connectable directed advertising → no connection indication from the iPad → DFU cannot proceed The accessory is advertising to the current resolvable address of the connected iPad. The bootloader starts directed advertising at nearly identical timing in both working and failing traces, approximately 456 ms after disconnect. The initial disconnect is normal in both cases: LL_TERMINATE_IND / Remote User Terminated Connection / reason 0x13 The problem occurs only after the accessory begins directed advertising. It seems like the iPad might be able to receive and listen to directed advertisement, however it seems to be unable to send back a connection indication. Hardware correlation observed so far We observed a correlation with Bluetooth controller vendor information visible in our BLE captures: FORMAT FOR FOLLOWING LINES Result -> Example device -> Observed controller vendor DFU succeeds -> iPad Air, 5th generation -> Broadcom DFU succeeds -> Other tested iPads, including one iPad with an A16-class platform -> Broadcom DFU fails -> One affected iPad with an A16-class platform -> MediaTek We want to be careful not to overstate this result: We have tested only one affected MediaTek-based iPad so far. The model string is MD3Y4LL/A and its current iOS version 26.6.1. The functioning Broadcomm iPads A16 we have tested that did not fail DFU process have model string MD7F4KN/A. The other iPad models we tested DFU on (which were all successful, albeit none of them were MediaTek chips, they were all Broadcomm) were: MRJN2KN/A, MM9C3KN/A, MQ6J3KN/A, MM6T3KN/A (the latter with iOS 26.6.1 as well, suggesting it is not necessarily an iPad OS version issue) We have not found a second MediaTek-based iPad to determine whether the behavior reproduces across that hardware. We initially suspected that recent non-cellular iPads might consistently use MediaTek, but this was disproved by the iPad Air, 5th generation we tested (MM9C3KN/A): it had no cellular connection and used Broadcom, and DFU worked normally. Therefore, we do not conclude that the issue is caused by MediaTek hardware. We only see a correlation worth investigating. What we have ruled out The target firmware image is not involved; failure occurs before any firmware data is transferred. The accessory reaches bootloader mode and sends directed advertisements at the expected time. The iOS Nordic DFU library already calls CoreBluetooth’s normal reconnect API: centralManager.connect(peripheral, options: nil) iOS does not expose an API allowing an app to create or send a raw Link Layer CONNECT_IND; therefore the application cannot directly work around controller-level connection behavior. The affected iPad does not provide a normal scanner/discovery callback for this directed bootloader advertisement, so matching by name or service UUID is not available as an application-layer workaround. Questions . Are there known CoreBluetooth, iPadOS, or Bluetooth-controller differences that can affect handling of BLE connectable directed advertisements, particularly when an accessory directs advertisements to a central using a resolvable private address? . Is there a recommended CoreBluetooth pattern for reconnecting to a known peripheral after it restarts into a legacy bootloader that uses directed advertising? . Does CBCentralManager.connect(_:options:) queue a pending connection request that should be serviced when a matching directed advertisement is received? If so, are there circumstances in which this behavior differs by iPad hardware or controller implementation? . Is there any public diagnostic information, entitlement, or supported API that could help us determine why a pending CoreBluetooth connection request does not result in a connection attempt in this scenario? . Does Apple recommend a specific compatibility approach for legacy BLE DFU bootloaders that use directed advertising, beyond updating the accessory firmware to use ordinary undirected advertising? . We can provide packet captures from both the working and failing cases, including timestamps, directed-advertisement target addresses, and the absence/presence of the subsequent connection indication. Thank you for any guidance on whether this is expected behavior, a known compatibility limitation, or if there is anything we could try on our end to hopefully resolve this issue.
Replies
1
Boosts
0
Views
289
Activity
2w
macOS grants half the connection-event airtime that iOS does, for the same accessory
We make a BLE peripheral that streams continuously. It's been running against Android, Windows, macOS and iOS for years. Android and Windows sit at ~1000 kbps and stay there — many host devices, many OS versions, no per-host tuning. macOS and iOS give us about half that. We've sniffed the BLE link using a Bluetooth sniffer to find out where it goes. Same board, same firmware, every session. Read off the air trace, not from host APIs: 2M PHY both directions (LL_PHY_UPDATE_IND 0x02 / 0x02) DLE max_tx_octets = 251 ATT MTU 247 15.00 ms interval, peripheral latency 0 no encryption no other BLE or BT Classic connections active during the session (all other devices removed and forgotten) WiFi turned off for around half of the sessions, didn't seem to make any difference Peripheral airtime per connection event: central airtime/event duty @ 15 ms throughput Android 11.14 ms 74% 995 kbps, sustained Windows ≥10.70 ms ≥71% ~1000 kbps, sustained macOS 6.96 ms 46% 561 kbps iOS 6.96 ms typical 46% ~560–600 kbps macOS comes out median 6.96, p90 6.96, max 7.09 across a whole session. Same number every time. iOS normally sits in the same place, with occasional brief excursions up to Android-like performance before dropping back down. Those excursions are worth describing, because they're the interesting part. In a handful of sessions out of many, iOS runs at 12.53 ms, 84% duty, ~1030 kbps. It never holds. It drops back inside 150 ms, with no renegotiation, no parameter change and no channel-map change anywhere in the trace. Sometimes it parks at 8.35 ms for ten seconds before moving again. This isn't us saying iOS is fine in practice — it clearly isn't, we can't ship against it. The point is that the radio and the stack demonstrably can fill a 12.53 ms event when they're allowed to, so whatever is holding them to 6.96 ms isn't a hardware ceiling. "It's a factor of ability" doesn't fit. This has been asked before and answered. In thread 774487, asked directly whether iOS limits packets per connection event to 4: "there is no 'limiting' going on as it is commonly understood ... We find that 4 is a more commonly true number than 6 or more some chipsets claim." In thread 770717, to a developer on iOS 18.2 running the same parameters we are: "iOS does not 'limit' the number of writes. It is just a factor of ability." Both answers need the accessory to be the variable. Ours isn't — same board, same firmware, minutes apart, and two non-Apple hosts take it to 1000 kbps and hold it indefinitely. The only thing that changes is which OS is acting as central. We don't think this can be explained by chipset capability when the chipset is the one thing held constant. It's airtime, not packet count. The "4 packets per connection event" number people quote here is the wrong unit, and we think that's why these threads go nowhere. Within one regime, as PDUs per event go up, PDU size goes down and the airtime doesn't move: iOS 9 PDUs @ 250.4 B -> 12.51 ms 10 PDUs @ 211.1 B -> 12.32 ms 11 PDUs @ 186.4 B -> 12.47 ms macOS 5 PDUs @ 239.4 B -> 6.73 ms 6 PDUs @ 178.1 B -> 6.60 ms Nothing is counting packets. The event closes on a clock. Count and airtime were the same measurement back when everything was 1M PHY and 27-byte PDUs — with 2M and DLE they aren't, and quoting a packet count now hides the mechanism instead of describing it. The peripheral isn't the limiter. The MD bit was set on the peripheral's last PDU in 2147 of 2148 connection events. It always had more data queued, and the central closed the event anyway. This isn't a new report. The same mechanism has been described here before. Thread 133092 (2019) reports macOS closing the connection event while the peripheral still has MD set — exactly what we measure. Thread 713349 reports "about 5 response packets per connection event," which is the same budget: 6.96 ms is 5 full-size PDUs. Thread 6025 reports a drop from 7 packets to 3. None of those received a reply. We're not raising them to relitigate old threads. The point is that three independent reports arriving at the same number across several years, on different accessories, points at a property of the scheduler rather than of anyone's hardware. On iOS, this looks like it changed in iOS 18. macOS has apparently behaved this way for years, going by the threads above. On iOS it's recent. We have video and screen recordings of this same peripheral tested on iOS 17, documented at the time as running consistently at around 1000 kbps. The behaviour described here started appearing when we moved to iOS 18. The firmware and the negotiated parameters are the same now as they were then, which points at a change in radio scheduling rather than anything on our side. What we're asking: Is the per-event airtime budget deliberate? ADG §55.6 and QA1931 cover interval, latency and timeout only. Neither mentions connection event length. Why do macOS and iOS give roughly half what Android and Windows give for the same accessory, and why can iOS reach 12.53 ms without staying there? Did anything change in iOS 18 around connection event scheduling? Is there anything we can do from the accessory or app side? We're already at 2M PHY, DLE 251, MTU 247 and the 15 ms floor. If the answer is "design for a floor, not a peak" — what's the floor? Right now we plan for ~560 kbps on Apple and roughly double that everywhere else, and that decides what we can ship, and whether we can count on Apple devices as a reliable platform for our product. Captures, recordings and analysis available if they're useful.
Replies
2
Boosts
0
Views
582
Activity
3w
Unable to display bluetooth paired device on iOS app
Hi there, I am working on bluetooth functionality of iOS and I have a feature that display all bluetooth paired devices on list view. Is there a way to get the list of paired device using swift programming. Many Thanks!
Replies
1
Boosts
0
Views
350
Activity
3w
BLE Channel Sounding: LL_CS_CONFIG_REQ rejected with Unsupported Feature Or Parameter Value
I'm testing Bluetooth Channel Sounding interoperability between an Apple device and a BLE peripheral. During Channel Sounding configuration, the peripheral sends an LL_CS_CONFIG_REQ, but the request is rejected by the central device with: LL_REJECT_EXT_IND Rejected Opcode: LL_CS_CONFIG_REQ Error Code: Unsupported Feature Or Parameter Value I would like to understand which parameter in the Channel Sounding configuration may be incompatible with the Apple device. Could the expert clarify which Channel Sounding configuration parameter would cause the Apple device to reject this LL_CS_CONFIG_REQ? if sniffer log is needed, I can send it via e-mail.
Replies
1
Boosts
0
Views
177
Activity
3w
AirPods Pro service visible in PacketLogger but absent from CoreBluetooth discovery
I’m investigating whether a consumer iPhone app can control AirPods Pro environmental listening settings using public APIs, while keeping all live audio processing inside the earbuds. On a real iPhone running iOS 26.6.1, with AirPods reporting model A3064 and firmware 8B41 in Settings: CoreBluetooth connects and successfully reads the manufacturer, model and firmware characteristics. Explicit discovery of service 7798082B-B7B7-45A6-9933-563492EFE04E returns no matching service. Unfiltered discovery completes without errors but also excludes that service. A system PacketLogger capture contains metadata mapping that service to handles 0x12–0x2B, and characteristic D5621CC1-F7AB-45DB-9403-9EAF744D5390 to value handle 0x18. System ATT reads of that handle receive responses. Our app performs no setting writes. We understand that system trace metadata does not establish third-party access. Is this service intentionally unavailable to third-party CoreBluetooth clients? Alternatively, is there a documented public connection, authorization or entitlement requirement that could explain its absence? If this service is unavailable, is there any supported API for controlling AirPods environmental amplification or frequency balance? A minimal Swift project and diagnostic report are available.
Replies
1
Boosts
0
Views
510
Activity
Sep ’26
Channel Sounding: supports(.channelSounding) is false on iPhone 17 Pro Max while Nearby Interaction reports the hardware as capable — what am I missing?
I'm trying to work out why Channel Sounding won't start on my device, and I'd be grateful for any pointers on what condition I haven't satisfied. What I see On an iPhone 17 Pro Max running iOS 27.0 beta (24A5390f), queried after the central manager reaches .poweredOn as the documentation requires: if #available(iOS 27.0, *) { print(CBCentralManager.supports(.channelSounding)) // false print(NISession.deviceCapabilities.supportsBluetoothChannelSounding) // true } No accessory or connection is involved — both are local queries. Because supports(.channelSounding) is false, the Core Bluetooth path fails with CBError code 13 ("Channel Sounding is not supported by the local or remote device"). I also tried calling startChannelSoundingSession(:) anyway, past my own capability check, against a connected peer; the same code 13 comes back from peripheral(:didCompleteChannelSoundingSession:), so it isn't merely an advisory check. The Nearby Interaction path gets further — its capability check passes, so session.run(_:) is called with NINearbyAccessoryConfiguration(bluetoothChannelSoundingIdentifier:previousBluetoothIdentifier:) against a paired, connected reflector — and then invalidates with NIErrorCodeSessionFailed (-5887). Same result with isCameraAssistanceEnabled set to both true and false. Apple's own "Measuring Distance Between Devices Using Channel Sounding" sample behaves identically on this device, so it isn't my code. What I've ruled out Querying before .poweredOn — the value is read in centralManagerDidUpdateState when the state is .poweredOn. Hardware — this is an iPhone 17 Pro Max, and Nearby Interaction's own capability check reports the hardware as capable. The Language & Region setting — changing it makes no difference. Beta staleness — updated across two betas, no change. The reflector — it implements the Ranging Service GATT server and the reflector role, and ranges successfully against another unit of its own model. What I'm unsure about The header comment for CBCentralManagerFeatureChannelSounding reads: The hardware and region supports channel sounding That's the only mention of "region" I can find in any Channel Sounding documentation — WWDC26 session 369 lists the N1 chip and the accessory-side requirements, but nothing about region, and there's no API to query that condition. My device is a South Korea market unit operating in South Korea, so I'm wondering whether that's what I'm hitting, but I have no way to confirm it. I'd also be glad to be told I'm simply wrong about something more mundane. Questions What conditions cause supports(.channelSounding) to return false on a device that has the N1 chip? Is region genuinely one of them, and if so, is it determined by the market the device was sold in, its current location, or something else? Should NISession.deviceCapabilities.supportsBluetoothChannelSounding be expected to agree with the Core Bluetooth check, or does it intentionally report hardware capability only? If the latter, is there a supported way to check Channel Sounding availability before running a session? For anyone with Channel Sounding working: which path are you using — Core Bluetooth's startChannelSoundingSession(_:), or NISession with NINearbyAccessoryConfiguration? And does supports(.channelSounding) return true for you? Question 3 is mostly to help me tell whether this is specific to my device. Thanks — happy to share more logs or a minimal reproducer if it's useful.
Replies
6
Boosts
1
Views
1.1k
Activity
Sep ’26
AccessorySetupKit connects and disconnects BLE accessory before .accessoryAdded when using .bluetoothPairingLE
I am using AccessorySetupKit on iOS 26 to set up a BLE accessory. My discovery descriptor includes .bluetoothPairingLE the bonding mechanism is LESC (Just Works without IO capability). let descriptor = ASDiscoveryDescriptor() descriptor.bluetoothServiceUUID = NordicServiceUUID.nus.toCBUUID() descriptor.supportedOptions = [.bluetoothPairingLE] My peripheral shows up in the picker and after selecting it ASK goes through a connection and disconnection cycle before calling .accessoryAdded event within my app. Logging on the peripheral side (nRF5 SDK 17) shows that the ASK picker connected, bonded successfully, and then triggered a remote terminated connection event (0x13). Prior implementation without .bluetoothPairingLE flag used did not disconnect from the peripheral before calling .accessoryAdded. The issue I found with this implementation is that the Pairing Modal would not always be presented and thus we are trying to leverage .bluetoothPairingLE flag for consistent behaviour across various iPhones / iOS combinations. My question, is it expected behaviour for AccessorySetupKit to connect, perform bonding, then disconnect from the peripheral prior to providing said accessory to the app via .accessoryAdded callback? I could find no documentation or community discussion discussing this behaviour or flow.
Replies
0
Boosts
0
Views
218
Activity
Sep ’26
IRK-resolvable BLE advertisements stops after screen turns off
Device and software: iPhone model: iPhone 15 Pro iOS 27 Public Beta 6 Build: 24A5430a BLE receivers: two independent ESP32's IRK has worked reliably on iOS 26 and past versions. Observed behavior: With the iPhone display on both BLE receivers detect advertisements that resolve correctly using the enrolled IRK. No more than 10 seconds after the display is turned off, the IRK-resolvable advertisements stop. The IRK identity returns immediately when a notification wakes the display or when I manually do. Bluetooth itself remains active while this happens. The receivers continue to see several strong advertisements from the phone with some unidentified rotating addresses. The unidentified addresses rotate periodically and cannot be associated with the enrolled IRK. Additional observations: When my Apple Watch is powered on and connected, the iPhone remains IRK-detectable while the screen is off. It stops again when watch is disconnected. Connecting Bluetooth headphones does not have the same effect. The IRK-resolvable advertisement stops even while music continues playing. Moving the affected phone between two receivers confirmed that the unidentified rotating advertisements physically followed the phone. The existing IRK remains valid because it resolves the phone again immediately whenever the display wakes. I couldnt find any intentional IRK, private-address or screen-off advertising change documented in the iOS 27 release notes or any discussions online. Has anyone else observed this on iOS 27?
Replies
0
Boosts
0
Views
238
Activity
Sep ’26
Peripheral reconnected while my app was force-quit and the app clearly ran. Is state restoration supposed to do that?
Central talking to one custom peripheral, CoreBluetooth state restoration enabled. Behavior I understand: iOS kills the app for memory pressure, peripheral does something, restoration relaunches into the background. Documented, and I have watched it work. Behavior I do not: I force-quit from the app switcher. The device had been unplugged and off for about a week. Plugged it back in and within a minute it had fresh data that only my app could have sent. So the app ran, and I never opened it. Everything I have read says force-quit is a hard opt-out until the user launches again. The only theory I have is that this is not the same event class as what I tested before. Earlier tests were all notifications from an already-connected peripheral. This time there was a connect request outstanding from before the force-quit, and it completed when the device came back. Possibly a pending connection completing is handled differently than traffic on a live link. I do not have instrumentation on this yet, so I cannot say whether it relaunched or was still resident, and I cannot rule out that the phone rebooted sometime during the week. Adding logging before I try to reproduce. Has anyone characterized this properly? Specifically whether a connectPeripheral pending from before a force-quit survives, and whether its completion can trigger relaunch. The docs do not draw that distinction.
Replies
1
Boosts
0
Views
292
Activity
Sep ’26
AccessorySetupKit: Combining Bluetooth and Wi‑Fi Aware PIN Pairing for a Dual-Transport Accessory
Dear Apple:I am developing an app and I would like to use Apple's AccessorySetupKit to complete the binding with an accessory. My accessory supports both Bluetooth and Wi-Fi Aware. I want to use AccessorySetupKit to complete both the Bluetooth pairing and the Wi-Fi Aware pairing with the accessory in one go. For Bluetooth, we also need to use the ANCS service, so the Bluetooth pairing requires a PIN code pop-up. However, we would like to skip this Bluetooth PIN code pairing, or combine it with the Wi-Fi Aware PIN code pairing into a single step. Is this possible under the current AccessorySetupKit framework? Because having the user confirm the PIN code twice does not seem like a great user experience. I would appreciate your help in answering this. Thank you.
Replies
0
Boosts
0
Views
340
Activity
Sep ’26