Bluetoothctl Set Passkey

Bluetoothctl set passkey

Here is what works thanks to kaylum :

$bluetoothctl
[bluetooth]# power on
Changing power on succeeded
[bluetooth]# discoverable on
Changing discoverable on succeeded
[bluetooth]# pairable on
Changing pairable on succeeded
[bluetooth]# agent NoInputNoOutput
Agent registered
[bluetooth]# default-agent
Default agent request successful

Then I pair the raspberry with my phone from the phone.

[NEW] Device XX:XX:XX:XX:XX:XX nameofthedevice
[CHG] Device XX:XX:XX:XX:XX:XX UUIDS:
--UUIDS--
[CHG] Device XX:XX:XX:XX:XX:XX Paired: yes

Bluetooth Pairing with DisplayOnly no passkey box appears

Understanding about pairing options mentioned in the URL are perfect, but BlueZ doesn't work in the same way. To simply the discussion here, please consider the explanation from Bluetooth Pairing blog from Bluetooth SIG.

To simplify, the below image is copied from the above mentioned blog.

Sample Image

So input can be three forms "No Input", "Yes/No" and "Keyboard". Output can be "No Output" and "Numeric Output".

In your case, Android is the initiator where you want to enter the passkey which is displayed in responder. So Android device's input is "Keyboard" and responder is "Numeric Output" capable.

To achieve your case, you need to specify "DisplayOnly" in responder (you are already correct) and "KeyboardOnly" or "KeyboardDisplay" in input Android device.

But BlueZ by default doesn't treat "KeyboardDisplay" as a separate option, instead it converts/considers it as "DisplayYesNO", see here in mgmt.txt API for more details. So your android input device acts as "DisplayYesNo" and results in confusion.

So you need to use "DisplayOnly" at responder and "KeyboardOnly" at initiator end. To experiment this use case with custom agent (not using bluetoothctl's agent), use the below sample example (Note: Not fully implemented, fscanf from stdin is bad :-(, etc.,)

/*
* gcc `pkg-config --cflags glib-2.0 gio-2.0` -Wall -Wextra -o ./bin/agent ./agent.c `pkg-config --libs glib-2.0 gio-2.0`
*/
#include <glib.h>
#include <gio/gio.h>
#include <stdio.h>

GMainLoop *loop;
GDBusConnection *con;
#define AGENT_PATH "/org/bluez/AutoPinAgent"

static void bluez_agent_method_call(GDBusConnection *conn,
const gchar *sender,
const gchar *path,
const gchar *interface,
const gchar *method,
GVariant *params,
GDBusMethodInvocation *invocation,
void *userdata)
{
int pass;
int entered;
char *opath;
GVariant *p= g_dbus_method_invocation_get_parameters(invocation);

g_print("Agent method call: %s.%s()\n", interface, method);
if(!strcmp(method, "RequestPinCode")) {
;
}
else if(!strcmp(method, "DisplayPinCode")) {
;
}
else if(!strcmp(method, "RequestPasskey")) {
g_print("Getting the Pin from user: ");
fscanf(stdin, "%d", &pass);
g_print("\n");
g_dbus_method_invocation_return_value(invocation, g_variant_new("(u)", pass));
}
else if(!strcmp(method, "DisplayPasskey")) {
g_variant_get(params, "(ouq)", &opath, &pass, &entered);
g_print("Path: %s Pass: %d Entered: %d\n", opath, pass, entered);
g_dbus_method_invocation_return_value(invocation, NULL);
}
else if(!strcmp(method, "RequestConfirmation")) {
g_variant_get(params, "(ou)", &opath, &pass);
g_print("Path: %s Pass: %d\n", opath, pass);
g_dbus_method_invocation_return_value(invocation, NULL);
}
else if(!strcmp(method, "RequestAuthorization")) {
;
}
else if(!strcmp(method, "AuthorizeService")) {
;
}
else if(!strcmp(method, "Cancel")) {
;
}
else
g_print("We should not come here, unknown method\n");
}

static const GDBusInterfaceVTable agent_method_table = {
.method_call = bluez_agent_method_call,
};

int bluez_register_agent(GDBusConnection *con)
{
GError *error = NULL;
guint id = 0;
GDBusNodeInfo *info = NULL;

static const gchar bluez_agent_introspection_xml[] =
"<node name='/org/bluez/SampleAgent'>"
" <interface name='org.bluez.Agent1'>"
" <method name='Release'>"
" </method>"
" <method name='RequestPinCode'>"
" <arg type='o' name='device' direction='in' />"
" <arg type='s' name='pincode' direction='out' />"
" </method>"
" <method name='DisplayPinCode'>"
" <arg type='o' name='device' direction='in' />"
" <arg type='s' name='pincode' direction='in' />"
" </method>"
" <method name='RequestPasskey'>"
" <arg type='o' name='device' direction='in' />"
" <arg type='u' name='passkey' direction='out' />"
" </method>"
" <method name='DisplayPasskey'>"
" <arg type='o' name='device' direction='in' />"
" <arg type='u' name='passkey' direction='in' />"
" <arg type='q' name='entered' direction='in' />"
" </method>"
" <method name='RequestConfirmation'>"
" <arg type='o' name='device' direction='in' />"
" <arg type='u' name='passkey' direction='in' />"
" </method>"
" <method name='RequestAuthorization'>"
" <arg type='o' name='device' direction='in' />"
" </method>"
" <method name='AuthorizeService'>"
" <arg type='o' name='device' direction='in' />"
" <arg type='s' name='uuid' direction='in' />"
" </method>"
" <method name='Cancel'>"
" </method>"
" </interface>"
"</node>";

info = g_dbus_node_info_new_for_xml(bluez_agent_introspection_xml, &error);
if(error) {
g_printerr("Unable to create node: %s\n", error->message);
g_clear_error(&error);
return 0;
}

id = g_dbus_connection_register_object(con,
AGENT_PATH,
info->interfaces[0],
&agent_method_table,
NULL, NULL, &error);
g_dbus_node_info_unref(info);
//g_dbus_connection_unregister_object(con, id);
/* call register method in AgentManager1 interface */
return id;
}

static int bluez_agent_call_method(const gchar *method, GVariant *param)
{
GVariant *result;
GError *error = NULL;

result = g_dbus_connection_call_sync(con,
"org.bluez",
"/org/bluez",
"org.bluez.AgentManager1",
method,
param,
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if(error != NULL) {
g_print("Register %s: %s\n", AGENT_PATH, error->message);
return 1;
}

g_variant_unref(result);
return 0;
}

static int bluez_register_autopair_agent(const char *cap)
{
int rc;

rc = bluez_agent_call_method("RegisterAgent", g_variant_new("(os)", AGENT_PATH, cap));
if(rc)
return 1;

rc = bluez_agent_call_method("RequestDefaultAgent", g_variant_new("(o)", AGENT_PATH));
if(rc) {
bluez_agent_call_method("UnregisterAgent", g_variant_new("(o)", AGENT_PATH));
return 1;
}

return 0;
}

static void cleanup_handler(int signo)
{
if (signo == SIGINT) {
g_print("received SIGINT\n");
g_main_loop_quit(loop);
}
}

int main(int argc, char **argv)
{
int id;
int rc;

if(argc < 2)
return 1;

if(signal(SIGINT, cleanup_handler) == SIG_ERR)
g_print("can't catch SIGINT\n");

con = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
if(con == NULL) {
g_print("Not able to get connection to system bus\n");
return 1;
}

loop = g_main_loop_new(NULL, FALSE);

id = bluez_register_agent(con);
if(id == 0)
goto fail;

rc = bluez_register_autopair_agent(argv[1]);
if(rc) {
g_print("Not able to register default autopair agent\n");
goto fail;
}

g_main_loop_run(loop);

fail:
g_dbus_connection_unregister_object(con, id);
g_object_unref(con);
return 0;
}

To experiment this, you must disable agent in bluetoothctl "agent off" and turn on the agent as,

Responder: ./bin/agent "DisplayOnly"
Initiator: ./bin/agent "KeyboardOnly"

When you try to pair from initiator, DisplayPasskey will be called in responder and displays 6 digit PIN and initiator will call RequestPasskey and takes the input PIN from stdin.

Bluetooth pairing using fixed PIN on bluez 5

I was able to get this working with the test scripts.

For anyone who is interested to know the details, please refer to my post on Raspberry Pi forum. Below is the link.

https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=195090&p=1221455#p1221455

Linux command line howto accept pairing for bluetooth device without pin

Try setting security to none in /etc/bluetooth/hcid.conf

http://linux.die.net/man/5/hcid.conf

This will probably only work for HCI devices (mouse, keyboard, spaceball, etc.). If you have a different kind of device, there's probably a different but similar setting to change.

How to setup Bluez 5 to ask pin code during pairing

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.



Related Topics



Leave a reply



Submit