I implemented the org.bluez.Agent1 interface using QDbus and I would like to set a fixed pin (that I will provide to the users) in order to authenticate all the pairing request and reject them if the pin is wrong. The agent capabilities should be "NoInputNoOutput" because the project will be deployed on the RaspberryPi 3 without keyboard or display. Is there a way to deal with this? Thank you
2 Answers
You should not initialize the capability as "NoInputOutput" for fixed key pairing. NoInputOutput means there is not display and there is no keyboard/UI possible for this device. Mentioning this capability for your Agent when registering with BlueZ means, instructing BlueZ (bluetoothd) not to call any Agent API for authentication.
This is typically useful to autopair without any manual intervention. You can see this sample code, which uses NoInputOutput capability to connect the device without any intervention.
What you need is "DisplayOnly" capability to instruct BlueZ to call "DisplayPinCode" or "DisplayPasskey" based on SSP support of your device.
You can implement DisplayPinCode/DisplayPasskey in your Agent to reply constant PIN always. So the Bluetooth device which tries to connect can use the same constant PIN for pairing.
Here Display Pin /Passkey is just the naming convention or hint to Agent developers to write wizard/UI or any form of display operations. But you can completely ignore the displaying operation and reply with static/constant 6 digit key for pairing.
Typically this Agent API is called by Bluez (in rasperry pi) when the device (iPhone/Android mobile/any bluetooth capable device) trying pair calls "RequestPasskey" or "RequestPinCode" from the device end.

- 2,130
- 2
- 14
- 27
-
I changed the agent capability to DisplayOnly as you suggested, but pairing from an Android device I noticed that only RequestConfirmation is called. I'm using the Android createBond method – Cristiano Jul 26 '18 at 10:56
-
@Cristiano: Sorry. RequestConfirmation also falls under display. So Android might defaults to that. Can you try "KeyboardOnly", this makes Android to enter key in UI. – Parthiban Jul 26 '18 at 16:06
-
Solved, I missed hciconfig hci0 sspmode 0 on the Raspberry. I was able to return a fixed string in RequestPin and inserted to pair with it. Thanks! However, I cannot see the Raspberry from iOS devices, do you know something about it? – Cristiano Jul 26 '18 at 16:11
-
@Cristiano Did you already set the "Discoverable" property on? – Parthiban Jul 26 '18 at 16:14
-
Yes, it' only an iOS problem. I can see the Raspberry from Android, Linux and Windows – Cristiano Jul 26 '18 at 16:21
-
1As I see, using `sspmode 1` we can't set fixed pin. We can't return anything from `Display Pin /Passkey`, since the result type of those methods is void. `RequestPasskey/RequestPinCode` isn't meant to generate a Pin, it's about asking the user to enter Pin he sees on the other pairing device (so bonding will fail if you return some other PIN, not the one that was generated by other device) – Shaddix Oct 15 '19 at 03:13
-
So the only way to set fixed PIN with bluez is using `sspmode 0` which isn't the best security practice nowdays. Please correct me if I'm wrong – Shaddix Oct 15 '19 at 03:15
-
@Shaddix It's not the case. I will share the working sample agent with fixed pin case. – Parthiban Oct 15 '19 at 10:12
-
@Shaddix As mentioned earlier, you can find the simple agent example here: https://gist.github.com/parthitce/7d9b221d30d8b1e1d3d741e0e42d9020 This is not well written. But this just gives overview about how the agent can respond fixed. I have used fscanf to get the PIN from user interaction, which is not recommended. You can replace by placing fixed PIN similarly in any API – Parthiban Oct 20 '19 at 09:52
-
Parthiban, the agent code you linked performs exactly as @Shaddix said. You return the passcode in RequestPasskey, and this passkey shall match the passkey generated (and displayed via DisplayPasskey) on the Initiator for pairing to be successful. – Bojan P. Feb 22 '22 at 14:39
-
The missing thing mentioned here is to set both devices to KeyboardOnly ( https://stackoverflow.com/a/52203098/5616255 ). However, you cannot change IO capabilities in Android or iOS ( https://stackoverflow.com/questions/61342299/set-io-capabilities-for-ble-pairing-on-ios ), meaning that the phone will have KeyboardDisplay, consequently always generating the random passkey, as Initiator or Responder (last image on https://www.bluetooth.com/blog/bluetooth-pairing-part-2-key-generation-methods/ ). – Bojan P. Feb 22 '22 at 15:00
We had the same issue in a project, and i moved on LE device do to the fact that apple device are only capable to connect to LE device for "safety" reasons.
I don't have that much ref to that but if this could help you in your researches.