如何将 BlueZ 配置为要求连接设备输入匹配的密钥?

2023-11-23

我正在尝试在嵌入式 Linux 设备上设置蓝牙,以便使用 SSP 模式,我的设备生成密码并在其显示屏上显示密码,并且要求远程端(例如用户的手机)输入匹配的密码才能使用才能成功配对。

我编写/注册了一个代理,将其模式设置为 DisplayOnly;我预计当设备连接时,将调用“RequestPasskey”回调,然后我的代理将能够生成并返回新的密码,并且远程端将需要输入相同的代码。我实际看到的行为是远程端正在生成自己的密码。

如果禁用 SSP 并使用旧配对,我可以实现类似所需行为的效果,但我宁愿不必这样做。

BlueZ 可以实现这种行为吗?


为了简单地讨论这里,请考虑来自的解释蓝牙配对博客来自蓝牙 SIG。

为了简化起见,下图是从上述博客复制的。

enter image description here

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

在您的情况下,您希望在嵌入式设备中生成密钥(我们可以将其命名为响应者),并在启动连接的设备中输入密钥(我们可以将其命名为发起者)。

为了实现这种情况,您需要指定,

响应者(嵌入式设备):作为“KeyboardOnly” 发起者:也作为“KeyboardOnly”

要对此进行实验,请使用以下示例代理,

/*
 * 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;
}

要进行实验,您必须在 bluetoothctl“agent off”中禁用代理并打开代理,如下所示:

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

当您尝试从发起端发起连接时,两端都会调用 RequestPasskey。您可以在两端输入相同的密钥。如果您想回复固定密钥 PIN,请在“回复者”末尾编辑“功能”的代理代码请求密码”,方法是回复固定 PIN 码并手动输入相同的 PIN 码,或者也从“发起者”端自动再次输入相同的 PIN 码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 BlueZ 配置为要求连接设备输入匹配的密钥? 的相关文章

  • Python if语句无法识别蓝牙信标

    这是 BeaconScanner py 文件用来查找和列出 ble 信标的 ScanUtility py 文件 This is a working prototype DO NOT USE IT IN LIVE PROJECTS impor
  • 从S3C6410板启动时无法在未知块(0,0)上挂载根文件系统

    我有一块S3C6410板 软件包中默认的 Linux 是 2 6 28 并且运行良好 我想用更新的内核升级它 我抓住了buildroot 2012 11版本 然后我获取 DVD 中的默认配置文件并用它编译内核 3 6 8 引导加载程序和根文
  • linux下c语言蓝牙编程

    我正在尝试在 linux ubuntu 中运行基本的 c 代码来搜索蓝牙设备 但我遇到了一些问题 通过使用命令sudo apt get install bluez 要安装所需的blueZ库 说明bluez已经是最新版本了 但出现错误 无法找
  • 将特定标头添加到 bitbake wget fetcher

    我需要设置一个特定的标头以使用以下命令从资源中获取存档wgetfetcher 类似于 wget header PRIVATE ACCESS TOKEN blablablablabla https some resource 如何使用该获取器
  • 使用 hciattach 通过 uart 进行蓝牙?

    我在用QN9021SoC工作在controller mode BLE 蓝牙核心规范 v4 0 它支持一些标准HCI命令以及一些供应商特定的命令 我正在尝试将其附加到我的ubuntu laptop 我使用的命令是hciattach hciat
  • 使用 libwebsockets 编译 libuv

    我正在尝试运行与 LWS 库一起安装的 libwebsockets test server 但它不会运行 因为 lwsts 31616 libuv support not generated in 我检查过 libuv 已安装 1 8 0
  • 在 ARM 9 板上显示图像

    我需要在嵌入式系统上显示图像 板卡配置如下 它是AT91sam9263 EK 运行Linux 2 6 20内核 这个板子有图像处理库吗 处理器是ARM 926EJ S 谢谢你们 如果帧缓冲区在 Linux 操作系统中没有激活 我知道它是在由
  • 如何使用QEMU学习ARM Linux内核开发?

    我想学习它 比如开发一些设备驱动程序等 并为此使用 QEMU 因为我没有像 beagle 板这样的 ARM 硬件板 你们有什么建议 我可以使用 Qemu 模拟器来学习 ARM 目标上的 Linux 内核吗 或者我应该尝试的任何其他选择 这取
  • 如何在嵌入式 Linux Raspberry Pi 上安装 GCC 和/或 apt

    我在树莓派 用于比特币矿工 上有一个预配置的 Linux 发行版 问题是这个发行版非常小 只有 busybox 用于基本命令 它没有包管理器 甚至没有 gcc 编译器 所以我的目标是在上面安装一个 gcc 编译器 这样我就可以进一步安装其他
  • numpy.distutils.system_info.NotFoundError:未找到 BLAS/LAPACK 库

    我在 buildroot 中添加 scikit learn 包 但它在构建步骤中需要 scipy 依赖项 所以我添加host python scipy in python scipy mk如下 HOST PYTHON SCIPY DEPEN
  • bluez5 中哪个工具取代了 gatttool?

    好像自从commit b1eb2c4cd057624312e0412f6c4be000f7fc3617 gatttool已被弃用 但我找不到任何信息 什么取代了 gattool 我在 gatttool 上研究过的每个 Python 蓝牙 L
  • 如何检查内核中SMP是否启用或禁用?

    我想知道如何检查我正在运行的机器 内核是否配置为 SMP 当然 我可以查看内核 config文件并可以搜索它 但是 问题是假设我没有源代码 我将如何检查 SMP 配置 有没有proc文件来检查吗 下面说我没有多核 cat proc cpui
  • 在 ubuntu core 14.04 上安装 libboost-all-dev 时依赖失败

    有人知道为什么我在 sudo apt get install libboost all dev 之后得到以下信息 Some packages could not be installed This may mean that you hav
  • 如何在 Yocto 中使用自己的设备树和修改后的内核配置?

    我正在努力用 yocto 构建一个自己的 嵌入式 Linux 它基于 SAMA5D3x MB SAMA5D3x CM RONETIX 和 SAMA5D35 我有两个问题 1 更改设备树 我基于以下内容构建图像 MACHINE sama5d3
  • Linux 中串行端口描述符块上的“关闭”函数

    最近我发现了一个对我来说很新的问题 我很感激建议 我正在 Linux 上使用 termios 函数进行串行通信 我实际上没有使用真正的串口 而是使用虚拟小工具串口驱动程序 dev ttyGS0 文件描述符以非阻塞方式打开 我的程序定期生成数
  • 如何在启动过程后切换Linux内核控制台?

    在我的嵌入式系统上 我通常使用 dev ttyS0 作 为主控制台 这是通过传递内核参数来实现的console dev ttyS0什么时候init尽其所能 getty在指定的同一设备上触发inittab by eg ttyS0 respaw
  • Yocto 添加自定义 UBoot 环境变量

    我正在尝试通过 Yocto 构建过程添加两个新的 u boot 环境变量 My file u boot imx 2021 04 bbappend包含 FILESEXTRAPATHS prepend THISDIR PN SRC URI fi
  • Yocto 构建上的 JAVA 安装错误

    我在 Poky Linux 系统上安装 Java 时遇到了很多麻烦 我正在使用 Yocto 构建我的系统 配置如下 本地配置文件 MACHINE intel corei7 64 DISTRO poky PACKAGE CLASSES pac
  • bluez 同时具有经典和低能耗设备

    Linux下的bluez是否可以同时连接多个经典和低能耗设备 bluez 网站提供这样的信息不是很有帮助 是的 我已经成功同时连接到 7 个低能耗设备 最大值因您使用的硬件而异 您还可以连接到多个经典设备 以下是我用于通过 L2CAP 连接
  • Linux 上的 mpc / mpd:如何播放本地 wav 文件

    我正在尝试将本地文件添加到 mpd 通过 mpc 并播放它 我的平台是OpenWRT嵌入式linux 因此 从手册页来看 它指出 mpc add

随机推荐

  • C++ tokenize std string [重复]

    这个问题在这里已经有答案了 可能的重复 如何在 C 中标记字符串 您好 我想知道如何使用 strtok 标记 std 字符串 string line hello world bye char pch strtok line c str 我收
  • Symfony形式:自定义调用的setter

    我有一个实体的 Symfony 表单自定义类型 我想自定义提交表单时执行的代码 但仅限于字段 例如 Symfony 默认会这样调用 entity gt setFoo value 我想做这样的调用 entity gt doSomething
  • R 和面向对象编程

    在 R 中 以一种或另一种方式进行面向对象编程是非常可能的 但是 与 Python 等不同 有很多方法可以实现面向对象 The R oo包 S3和S4班 参考课 the 原型包 我的问题是 What majorR 中 OO 编程的这些方式有
  • 与发布后的实际下载大小相比,testflight 应用程序大小是否膨胀很大?

    我用 Unity 构建了一个 iOS 游戏 我将其上传到 App Store 启用了位码 IPA 约为 200 mb 在 iTunes Connect 上 它显示我的构建尺寸约为每个设备 30mb 我很高兴看到 但是当我将构建添加到 Tes
  • 如何在asp.net c#中将日期字符串“dd/MM/yyyy”格式转换为“MM/dd/yyyy”?

    我想在 C 中将字符串日期格式 dd MM yyyy 转换为 MM dd yyyy 例子 string d 25 02 2012 i want to convert into 02 25 2012 您可以将其解析为DateTime对象使用D
  • 方法签名中的 Final 关键字[重复]

    这个问题在这里已经有答案了 可能的重复 接口方法中的最终参数 有什么意义 在尝试尝试一些事情时 我遇到了其中描述的问题这一页 interface B public int something final int a abstract cla
  • 如何恢复之前显示的Fragment?

    我在我的项目中使用兼容性包 v4 但在保留Fragment从视图中删除后周围 我有我的Activity显示 2 个片段 左侧是菜单框架 右侧是内容窗格 菜单框架有 3 个可以显示的不同菜单 片段 这就是我替换菜单片段的方式 public v
  • R Shiny:如何将数据表添加到动态创建的选项卡

    我目前正在尝试创建动态创建的数据表 每个数据表都有自己的选项卡 选项卡的数量由用户确定 我已经使用了来自的代码这个帖子作为一个框架 我能够动态创建选项卡 但我不知道如何将数据表添加到选项卡 数据表也由用户输入确定 因此 例如 在 ui R
  • 具有验证功能的独特 CD-KEY 生成算法

    我正在尝试创建一个独特的 CD KEY 放入我们产品的包装盒中 就像用户用来注册产品的标准软件盒中的普通 CD KEY 一样 然而 我们不销售软件 我们销售的是用于犯罪和医疗目的的 DNA 采集套件 用户将通过邮件收到带有 CD KEY 的
  • Angular.js 中哪些“东西”可以注入到其他东西中?

    我很难理解 Angular 中的依赖注入 所以我的问题是 谁能解释一下我们可以将哪些 类型 如控制器 工厂 提供者等 注入到其他类型中 包括相同 类型 的其他实例 我真正要找的是这张表 上面写满了 y n 对于具有相同行 列的单元格 这意味
  • 与组件相比,使用服务有哪些优点和缺点?

    在过去的几个月里 我一直致力于最新的 net 框架中的项目 我觉得在最新的 net 版本中 鼓励 服务 而不是组件 那是对的吗 我在silver light中看到过 我是silver light的初学者 所有的DB层操作都暴露为服务 不知道
  • 如何在Spring的CAS服务属性中正确设置服务URL

    当使用 Spring Security CAS 时 我总是遇到发送到 CAS 的回调 URL 即服务属性 的小障碍 我看过很多例子 例如this and this但它们都使用硬编码的 URL 甚至Spring 的 CAS 文档 典型的剪辑看
  • 我如何创建一个每次在 tkinter 中显示帧时运行的方法

    我有一个 GUI 应用程序 有几个窗口和按钮可以前进和后退 为此 我使用控制器并在每次窗口更改时将框架提升到顶部 这是我的控制器代码和典型框架 import Tkinter as tk python from tkFileDialog im
  • Django OperationalError:无法为连接创建新进程

    今天早上 在让 Django storages Boto 和 Django compressor 将静态文件放到 S3 上之后 我今天早上开始在生产环境中遇到此错误 尽管我不知道这是否相关 OperationalError could no
  • 如何持久存储目录中文件的值?

    我正在使用 C 在 VS2005 中开发 Windows 应用程序 在我的项目中 我生成 dll 并将它们存储在一个目录中 这些 dll 将被命名为 TestAssembly1 TestAssembly2 TestAssembly3 等 所
  • Node.js 连接 ftp 并下载文件

    你好 我下载了这个 npm 模块来连接到我的 ftp 节点FTPS 连接等级 var FTPS require ftps var ftps new FTPS host myhost username user password mypw p
  • Interlocked.CompareExchange 是否使用内存屏障?

    我正在阅读乔 达菲 Joe Duffy 的帖子读写易失性和时效性 我试图理解帖子中最后一个代码示例的一些内容 while Interlocked CompareExchange ref m state 1 0 0 m state 0 whi
  • 使用位置粘性删除不需要的空间

    我正在尝试使用position sticky在旋转的元素上 但我在顶部获得了额外的空间 此外 粘性元素必须停止的地方 在父元素的末尾 它会移到外面 请注意 我需要控制来选择粘性元素和左窗口侧之间放置的像素数 检查第二个屏幕截图以了解这两个问
  • Google 自定义搜索下一页

    我有以下代码 但我不知道如何打印下一页的链接 如何转到下一页 usr bin python2 4 coding utf 8 import pprint from apiclient discovery import build def ma
  • 如何将 BlueZ 配置为要求连接设备输入匹配的密钥?

    我正在尝试在嵌入式 Linux 设备上设置蓝牙 以便使用 SSP 模式 我的设备生成密码并在其显示屏上显示密码 并且要求远程端 例如用户的手机 输入匹配的密码才能使用才能成功配对 我编写 注册了一个代理 将其模式设置为 DisplayOnl