Android 蓝牙配对显示仅显示无密钥框

Android 蓝牙配对显示仅显示无密钥框,android,bluetooth,bluez,Android,Bluetooth,Bluez,我正在尝试为linux配置蓝牙芯片,以便与android手机配对。我将有一个可以显示6位密钥的显示器,因此我尝试将Bluetoothctl代理设置为DisplayOnly 根据这篇文章的表格 如果响应者是DisplayOnly,而启动器(Android)是KeyboardDisplay,则应使用密钥输入,响应者显示代码,启动器输入代码 实际情况是,Android在尝试配对时没有显示任何内容,bluetoothctl输出显示一个数字比较响应yes/no:即使我指定我没有任何输入(仅显示) 我怎样才

我正在尝试为linux配置蓝牙芯片,以便与android手机配对。我将有一个可以显示6位密钥的显示器,因此我尝试将Bluetoothctl代理设置为DisplayOnly

根据这篇文章的表格 如果响应者是DisplayOnly,而启动器(Android)是KeyboardDisplay,则应使用密钥输入,响应者显示代码,启动器输入代码

实际情况是,Android在尝试配对时没有显示任何内容,bluetoothctl输出显示一个数字比较响应yes/no:即使我指定我没有任何输入(仅显示)


我怎样才能让bluez代理真正像DisplayOnly一样工作,从而显示一个密码供我进入Android?

理解URL中提到的配对选项是完美的,但bluez的工作方式不同。简单地讨论一下,请考虑蓝牙Sig.

的解释。 为了简化,下面的图片是从上面提到的博客中复制的

因此,输入可以是三种形式:“无输入”、“是/否”和“键盘”。输出可以是“无输出”和“数字输出”

在您的情况下,Android是您想要输入显示在responder中的密钥的启动器。所以安卓设备的输入是“键盘”,应答器是“数字输出”功能

为了实现您的情况,您需要在响应器中指定“DisplayOnly”(您已经正确),并在输入Android设备中指定“KeyboardOnly”或“KeyboardDisplay”

但BlueZ默认情况下不会将“KeyboardDisplay”视为单独的选项,而是将其转换/视为“DisplayYesNO”,以了解更多详细信息。因此,您的android输入设备充当“DisplayYesNo”并导致混乱

所以您需要在响应端使用“DisplayOnly”,在发起端使用“KeyboardOnly”。要使用定制代理(不使用bluetoothctl的代理)测试此用例,请使用以下示例(注意:未完全实现,stdin中的fscanf不好:-(,等等)


当您尝试从发起方配对时,将在应答器中调用DeSpAccess密钥,并显示6位PIN,发起方将调用RequestPasskey并从STDIN获取输入PIN。

< P>关于URL中提到的配对选项的理解是完美的,但Brasz不以相同的方式工作。来自Bluetooth SIG的解释

为了简化,下面的图片是从上面提到的博客中复制的

因此,输入可以是“无输入”、“是/否”和“键盘”三种形式。输出可以是“无输出”和“数字输出”

在你的例子中,Android是你想要输入密码的发起者,密码显示在responder中。所以Android设备的输入是“键盘”,responder可以“数字输出”

为了实现您的情况,您需要在响应器中指定“DisplayOnly”(您已经正确),并在输入Android设备中指定“KeyboardOnly”或“KeyboardDisplay”

但BlueZ默认情况下不会将“KeyboardDisplay”视为单独的选项,而是将其转换/视为“DisplayYesNO”,以了解更多细节。因此,您的android输入设备充当“DisplayYesNO”,并导致混淆

因此,您需要在响应程序端使用“DisplayOnly”,在启动器端使用“KeyboardOnly”。要使用定制代理(不使用bluetoothctl的代理)测试此用例,请使用下面的示例(注意:未完全实现,stdin的fscanf不好:-(,等等)


当您尝试与initiator配对时,DisplayPasskey将在responder中调用,并显示6位PIN,initiator将调用RequestPasskey并从stdin获取输入PIN。

Wow感谢您的详细回答。我一直在考虑添加自定义代理,但目标操作系统是tinycore,因此我在编译代理时遇到问题t的盒子,但我会继续尝试,看看这是否有效!@Tyler:谢谢。如果答案真的回答了你的问题,请接受它:-)所以我在我的应答器上运行自定义代理,但是如果启动器是Android,我如何在启动器上运行它呢?我看不出一种方法可以只使用Android键盘advise@Tyler我不确定Android end。好的,谢谢,我接受了这个答案,因为它回答了为什么不使用密钥项的问题,我将为settin打开一个新问题g android to Keyboard Only谢谢你的详细回答。我一直在考虑添加一个自定义代理,但目标操作系统是tinycore,因此我在编译现成的代理时遇到了问题,但我会继续尝试,看看这是否有效!@Tyler:谢谢。如果它真的回答了你的问题,请接受答案:-)所以我在我的响应程序上运行定制代理,但是如果启动器是Android,我如何在启动器上运行它呢?我看不出一种方法可以只制作Android键盘advise@Tyler我不确定安卓终端。好的,谢谢,我接受了这个答案,因为它回答了为什么不使用密码输入的问题,我将打开一个新的问题,只将安卓设置为键盘
/*
 * 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;
}
Responder: ./bin/agent "DisplayOnly"
Initiator: ./bin/agent "KeyboardOnly"