I’m debugging a custom BLE HID device on iPhone. It is a composite HID mouse + keyboard dongle.
Setup:
- Hardware: Seeed XIAO nRF52840
- Firmware: Adafruit Bluefruit Arduino / BLEHidAdafruit
- BLE HID report map: stock Adafruit composite HID with keyboard, consumer, and mouse reports
- GAP/advertising appearance: HID_MOUSE
- iOS adopts the device as an AssistiveTouch pointer
- Mouse movement and clicks work correctly
Keyboard symptom:
- Lowercase/unshifted characters type correctly.
- Shifted characters lose the Shift modifier during text input:
- A -> a
- T -> t
- DoorDash -> doordash
- ! -> 1
- @ -> 2
- # -> 3
- { -> [
- } -> ]
Confirmed:
- The iOS app sends the exact intended string to the dongle.
- Firmware receives the exact string.
- Firmware computes and sends the expected HID modifier/keycode:
- A sends modifier 0x02 + HID_KEY_A
- ! sends modifier 0x02 + HID_KEY_1
- A lone isolated "A" still lands as "a", so this does not appear to be a timing or repeated-key issue.
- Cmd+Space works from the same HID keyboard report path and opens Spotlight.
- Full Keyboard Access is off.
- Turning AssistiveTouch off does not fix it.
- The iPhone never shows "Hardware Keyboard" settings for this device, even when searching Settings.
Question: Is there a documented distinction on iOS between accepting BLE HID keyboard reports for global shortcuts, such as Cmd+Space, and admitting the same device as a full Hardware Keyboard for text composition?
In particular:
- Does the absence of Hardware Keyboard settings mean iOS has not classified the device as a real external keyboard?
- Can a composite BLE HID device advertised as HID_MOUSE be accepted for pointer input but have Shift ignored for text input?
- Does iOS require a different GAP appearance, HID report-map structure, report ordering, or separate keyboard identity for Shift/modifier text composition to work?
- Is there a recommended way to build a BLE HID device that preserves AssistiveTouch pointer behavior while also being treated as a full external keyboard?