Android blueZ HCI(一):hciconfig实现及常用方法

本文详细解析了HCiconfig实现及其常用方法,包括hciconfig的执行文件位置、代码实现、命令解析、命令执行过程以及常用命令介绍。涵盖了如何启动蓝牙、查看蓝牙信息、启动和关闭蓝牙等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关键词:hciconfighcitool  hcidump
作者:xubin341719(欢迎转载,请注明作者,请尊重版权,谢谢!)
欢迎指正错误,共同学习、共同进步!!

Android blueZ HCI(一):hciconfig实现及常用方法
Android blueZ hci(二):hcitool hcidump常用方法

一、Hciconfig
1、adb shell 下,hciconfig 执行文件的位
/system/xbin/hciconfig


相应目录下Android.mk文件,生成hciconfig

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #  
  2. # hciconfig  
  3. #  
  4. include $(CLEAR_VARS)  
  5. LOCAL_SRC_FILES:= \  
  6.     csr.c \  
  7.     csr_h4.c \  
  8.     hciconfig.c  
  9. ………………  
  10. LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)  
  11. LOCAL_MODULE_TAGS :optional  
  12. LOCAL_MODULE:=hciconfig  
  13. include $(BUILD_EXECUTABLE)  

2、hciconfig代码实现
idh.code\external\bluetooth\bluez\tools\hciconfig.c
main函数主要有两部分功能:main_options操作,命令的执行;
下面我们分两部分分析

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int main(int argc, char *argv[])  
  2. {  
  3.     int opt, ctl, i, cmd=0;  
  4. //(1)、hciconfig两个命main_options,help和all两个命令;  
  5.     while ((opt=getopt_long(argc, argv, "ah", main_options, NULL)) != -1) {  
  6.         switch(opt) {  
  7.         case 'a':  
  8.             all = 1;  
  9.             break;  
  10.         case 'h':  
  11.         default:  
  12.             usage();  
  13.             exit(0);  
  14.         }  
  15.     }  
  16. //(2)、命令执行部分  
  17.     argc -optind;  
  18.     argv += optind;  
  19.     optind = 0;  
  20.   
  21.     /* Open HCI socket  */  
  22.     if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) {  
  23.         perror("Can't open HCI socket.");  
  24.         exit(1);  
  25.     }  
  26.   
  27.     if (argc < 1) {  
  28.         print_dev_list(ctl, 0);  
  29.         exit(0);  
  30.     }  
  31.   
  32.     di.dev_id = atoi(argv[0] + 3);  
  33.     argc--; argv++;  
  34.   
  35.     if (ioctl(ctl, HCIGETDEVINFO, (void *) &di)) {  
  36.         perror("Can't get device info");  
  37.         exit(1);  
  38.     }  
  39.   
  40.     if (hci_test_bit(HCI_RAW, &di.flags) &&  
  41.             !bacmp(&di.bdaddr, BDADDR_ANY)) {  
  42.         int dd = hci_open_dev(di.dev_id);  
  43.         hci_read_bd_addr(dd, &di.bdaddr, 1000);  
  44.         hci_close_dev(dd);  
  45.     }  
  46.   
  47.     while (argc > 0) {  
  48.         for (i = 0; command[i].cmd; i++) {  
  49.             if (strncmp(command[i].cmd, *argv, 5))  
  50.                 continue;  
  51.   
  52.             if (command[i].opt) {  
  53.                 argc--; argv++;  
  54.             }  
  55.   
  56.             command[i].func(ctl, di.dev_id, *argv);  
  57.             cmd = 1;  
  58.             break;  
  59.         }  
  60.         argc--; argv++;  
  61.     }  
  62.   
  63.     if (!cmd)  
  64.         print_dev_info(ctl, &di);  
  65.   
  66.     close(ctl);  
  67.     return 0;  
  68. }  

(1)、hciconfig两个命main_options,help和all两个命令

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int main(int argc, char *argv[])  
  2. {  
  3.     int opt, ctl, i, cmd=0;  
  4. //1)、hciconfig两个命main_options,help和all两个命令;  
  5.     while ((opt=getopt_long(argc, argv, "ah", main_options, NULL)) != -1) {//1)、main_options;  
  6.         switch(opt) {  
  7.         case 'a':  
  8.             all = 1;  
  9.             break;//2)、如果是all命令执行下去;  
  10.         case 'h':  
  11.         default:  
  12.             usage();//3)、如果是help命令打印出命令使用方法;  
  13.             exit(0);  
  14.         }  
  15.     }  
  16. ………………  
  17. }  

1)、main_options
while((opt=getopt_long(argc, argv, "ah", main_options, NULL)) != -1) {
getopt被用来解析命令行选项参数,getopt_long,解析命令参数支持长选项。即一对短横线、一个描述性选项名称,还可以包含一个使用等号连接到选项的参数。

http://blog.youkuaiyun.com/slmmlk2011_2/article/details/7964218中有详细介绍。
即:hciconfig–all

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. main_options  
  2. static struct option main_options[] = {  
  3.     { "help",   0, 0, 'h' },  
  4.     { "all",    0, 0, 'a' },  
  5.     { 0, 0, 0, 0 }  
  6. };  

2)、ops 解析出来数据,如果是a,打印出蓝牙相关信息

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. case 'a':  
  2.         all = 1;  
  3.         break;  

后面这部分和命令解析一起分析。

3)、如果是help命令,打印出命令使用方法;

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. case 'h':  
  2. default:  
  3.     usage();  
  4. exit(0);  

如果是help 执行usage这个函数。下面分析这个函数
idh.code\external\bluetooth\bluez\tools\hciconfig.c

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static void usage(void)  
  2. {  
  3.     int i;  
  4.     printf("hciconfig - HCI device configuration utility\n");  
  5.     printf("Usage:\n"  
  6.         "\thciconfig\n"  
  7.         "\thciconfig [-a] hciX [command]\n");  
  8.     printf("Commands:\n");  
  9.     for (i=0; command[i].cmd; i++)  
  10.         printf("\t%-10s %-8s\t%s\n", command[i].cmd,  
  11.         command[i].opt ? command[i].opt : " ",  
  12.         command[i].doc);  
  13. }  

这个函数比较简单,就是不command[]结构体中的命令字符串打印出来:下面两个截图就一目了然了:

命令执行结果如下:


[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static struct {  
  2.     char *cmd;//命令,比如hciconfig up;  
  3.     void (*func)(int ctl, int hdev, char *opt);//命令执行函数;  
  4.     char *opt;//  
  5.     char *doc;//命令描述  
  6. } command[] = {  
  7.     { "up",     cmd_up,     0,      "Open and initialize HCI device" },  
  8.     { "down",   cmd_down,   0,      "Close HCI device" },  
  9.     { "reset",  cmd_reset,  0,      "Reset HCI device" },  
  10. ………………  
  11. }  
这部分以:{ "up",           cmd_up,            0,               "Open and initialize HCIdevice" },为例说明

使用up命令时,会调用到,cmd_up这个函数:
idh.code\external\bluetooth\bluez\tools\hciconfig.c

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static void cmd_up(int ctl, int hdev, char *opt)  
  2. {  
  3.     /* Start HCI device */  
  4.     if (ioctl(ctl, HCIDEVUP, hdev) < 0) {  
  5.         if (errno == EALREADY)  
  6.             return;  
  7.         fprintf(stderr, "Can't init device hci%d: %s (%d)\n",  
  8.                         hdev, strerror(errno), errno);  
  9.         exit(1);  
  10.     }  
  11. }  

(2)、命令执行部分

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Main()  
  2. {  
  3. ………………  
  4.     argc -optind;  
  5.     argv += optind;  
  6.     optind = 0;  
  7.   
  8.     /* Open HCI socket  *///1)、打开HCI socket通信  
  9.     if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) {/  
  10.         perror("Can't open HCI socket.");  
  11.         exit(1);  
  12.     }  
  13.   
  14.     if (argc < 1) {  
  15.         print_dev_list(ctl, 0);  
  16.         exit(0);  
  17.     }  
  18.   
  19.     di.dev_id = atoi(argv[0] + 3);  
  20.     argc--; argv++;  
  21. //2)、通过ioctl获取HCI驱动信息  
  22.     if (ioctl(ctl, HCIGETDEVINFO, (void *) &di)) {  
  23.         perror("Can't get device info");  
  24.         exit(1);  
  25.     }  
  26. //3)、hci_test_bit  bacmp  
  27.     if (hci_test_bit(HCI_RAW, &di.flags) &&  
  28.             !bacmp(&di.bdaddr, BDADDR_ANY)) {  
  29.         int dd = hci_open_dev(di.dev_id);  
  30.         hci_read_bd_addr(dd, &di.bdaddr, 1000);  
  31.         hci_close_dev(dd);  
  32.     }  
  33. //4)命令执行  
  34.     while (argc > 0) {  
  35.         for (i = 0; command[i].cmd; i++) {  
  36.             if (strncmp(command[i].cmd, *argv, 5))  
  37.                 continue;  
  38.   
  39.             if (command[i].opt) {  
  40.                 argc--; argv++;  
  41.             }  
  42.   
  43.             command[i].func(ctl, di.dev_id, *argv);  
  44.             cmd = 1;  
  45.             break;  
  46.         }  
  47.         argc--; argv++;  
  48.     }  
  49.   
  50.     if (!cmd)//没有相应的命令打印出  
  51.         print_dev_info(ctl, &di);  
  52. //5)、关闭ctl,完成操作  
  53.     close(ctl);  
  54.     return 0;  
  55. }  

1)、打开HCI socket通信

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* Open HCI socket  */  
  2.     if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) {  
  3. int socket(int domain, int type, int protocol);  

参数说明:
  domain:
指明所使用的协议族,通常为PF_INET,表示TCP/IP协议;
  type:参数指定socket的类型,基本上有三种:数据流套接字、数据报套接字、原始套接字
  protocol:通常赋值"0"。

程序中蓝牙建立:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. damain:使用AF_BLUETOOTH;  
  2. idh.code\3rdparty\bluetooth\Trout_BT\special\android\kernel\include\net\bluetooth\bluetooth.h  
  3. #define AF_BLUETOOTH    31  
  4. type: SOC_SEQPACKET,以Packet为单位读取,SOC_RAW:原始socket  
  5. enum sock_type {  
  6.     SOCK_STREAM = 1,  
  7.     SOCK_DGRAM  = 2,  
  8.     SOCK_RAW    = 3,  
  9.     SOCK_RDM    = 4,  
  10.     SOCK_SEQPACKET  = 5,  
  11.     SOCK_DCCP   = 6,  
  12.     SOCK_PACKET = 10,  
  13. };  
  14. protocol:使用相应建立的Socket的protocol,不同类型的入L2CAP、HCI、SCO……  
  15. #define BTPROTO_L2CAP   0  
  16. #define BTPROTO_HCI 1  
  17. #define BTPROTO_SCO 2  
  18. #define BTPROTO_RFCOMM  3  
  19. #define BTPROTO_BNEP    4  
  20. #define BTPROTO_CMTP    5  
  21. #define BTPROTO_HIDP    6  
  22. #define BTPROTO_AVDTP   7  
2)、通过ioctl获取HCI驱动信息,写入struct hci_dev_info di结构体

         if(ioctl(ctl, HCIGETDEVINFO, (void *) &di))
idh.code\3rdparty\bluetooth\Trout_BT\special\android\kernel\include\net\bluetooth\hci.h相关命令的定义

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #define HCIGETDEVLIST   _IOR('H', 210, int)  
  2. #define HCIGETDEVINFO   _IOR('H', 211, int)  
  3. #define HCIGETCONNLIST  _IOR('H', 212, int)  
  4. #define HCIGETCONNINFO  _IOR('H', 213, int)  
  5. #define HCIGETAUTHINFO  _IOR('H', 215, int)  
  6.     di对应的数据结构  
  7. static struct hci_dev_info di;  
  8. struct hci_dev_info {  
  9.     __u16 dev_id;  
  10.     char  name[8];  
  11.     bdaddr_t bdaddr;  
  12.     __u32 flags;  
  13.     __u8  type;  
  14.     __u8  features[8];  
  15.     __u32 pkt_type;  
  16.     __u32 link_policy;  
  17.     __u32 link_mode;  
  18.     __u16 acl_mtu;  
  19.     __u16 acl_pkts;  
  20.     __u16 sco_mtu;  
  21.     __u16 sco_pkts;  
  22.     struct hci_dev_stats stat;  
  23. };  
3)、hci_test_bit bacmp
[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. if (hci_test_bit(HCI_RAW, &di.flags) &&  
  2.         !bacmp(&di.bdaddr, BDADDR_ANY)) {  
  3.     int dd = hci_open_dev(di.dev_id);  
  4.     hci_read_bd_addr(dd, &di.bdaddr, 1000);  
  5.     hci_close_dev(dd);  
  6. }  

判断di中相关参数。
hci_test_bit检测*addr的第nr位是否为1(*addr右起最低位为第0位)

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static inline int hci_test_bit(int nr, void *addr)  
  2. {  
  3.     return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));  
  4. }  

4)、命令执行,这部分是命令实现的部分

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. while (argc > 0) {  
  2.     for (i = 0; command[i].cmd; i++) {  
  3.         if (strncmp(command[i].cmd, *argv, 5))//通过for循环比较第二个参数  
  4.             continue;  
  5.   
  6.         if (command[i].opt) {  
  7.             argc--; argv++;  
  8.         }  
  9.   
  10.         command[i].func(ctl, di.dev_id, *argv);//如果参数对应,就执行相应的命令函数  
  11.         cmd = 1;  
  12.         break;  
  13.     }  
  14.     argc--; argv++;  
  15. }  
  16. if (!cmd)//没有相应的命令打印出  
  17.     print_dev_info(ctl, &di);  

a、如:if (strncmp(command[i].cmd, *argv, 5))// 通过for循环比较第二个参数
| 如命令:hciconfighci0 commands
argv 的值就为:commands字符串,如果5个字符相等。

b、如果对应,就执行相应的命令函数

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. command[i].func(ctl, di.dev_id, *argv);  
c、如果是commands命令 :对应command[]结构体中的数组
[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. { "commands",   cmd_commands,   0,      "Display supported commands" },  

command[i].func = cmd_commands
对应commands 的实现函数cmd_commands函数的实现:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static void cmd_commands(int ctl, int hdev, char *opt)  
  2. {  
  3.     uint8_t cmds[64];  
  4.     char *str;  
  5.     int i, n, dd;  
  6.   
  7.     dd = hci_open_dev(hdev);  
  8.     if (dd < 0) {  
  9.         fprintf(stderr, "Can't open device hci%d: %s (%d)\n",  
  10.                         hdev, strerror(errno), errno);  
  11.         exit(1);  
  12.     }  
  13.   
  14.     if (hci_read_local_commands(dd, cmds, 1000) < 0) {  
  15.         fprintf(stderr, "Can't read support commands on hci%d: %s (%d)\n",  
  16.                         hdev, strerror(errno), errno);  
  17.         exit(1);  
  18.     }  
  19.   
  20.     print_dev_hdr(&di);  
  21.     for (i = 0; i < 64; i++) {  
  22.         if (!cmds[i])  
  23.             continue;  
  24.   
  25.         printf("%s Octet %-2d = 0x%02x (Bit",  
  26.             i ? "\t\t ": "\tCommands:", i, cmds[i]);  
  27.         for (n = 0; n < 8; n++)  
  28.             if (cmds[i] & (1 << n))  
  29.                 printf(" %d", n);  
  30.         printf(")\n");  
  31.     }  
  32.   
  33.     str = hci_commandstostr(cmds, "\t", 71);  
  34.     printf("%s\n", str);  
  35.     bt_free(str);  
  36.   
  37.     hci_close_dev(dd);  
  38. }  
  39. 这个是针对每个命令实现的具体函数。  
  40. //5)、关闭ctl,完成操作  
  41.     close(ctl);  
  42.     return 0;  

3、hciconfig命令常用方法:
(1)、帮助命令:查看hciconfig支持的命令和用法
hciconfig –h或者hciconfig  --hlep

(2)、查看蓝牙相关信息

hciconfig –a


[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. root@android:/ # hciconfig -a  
  2. hciconfig -a  
  3. hci0:   Type: BR/EDR  Bus: UART//蓝牙的接口类型,这个是UART的,还有USB、PCI…………  
  4.         BD Address: 00:16:53:96:22:53  ACL MTU: 1021:8  SCO MTU: 120:10//蓝牙地址  
  5.         UP RUNNING PSCAN//命令状态  
  6.         RX bytes:2846 acl:0 sco:0 events:67 errors:0  
  7.         TX bytes:2034 acl:0 sco:0 commands:80 errors:0  
  8.         Features: 0xff 0xff 0x8d 0xfe 0x9b 0xbf 0x79 0x83  
  9.         Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3//支持数据包  
  10.         Link policy: RSWITCH HOLD SNIFF PARK  
  11.         Link mode: SLAVE ACCEPT//连接的类型,是主设备、从设备  
  12.         Name: 'sp8825c1'//蓝牙名称  
  13.         Class: 0x5a020c//蓝牙的类型  
  14.         Service Classes: Networking, Capturing, Object Transfer, Telephony//支持的类型  
  15.         Device Class: Phone, Smart phone  
  16.         HCI Version: 2.1 (0x4)  Revision: 0x1250//HCI版本  
  17.         LMP Version: 2.1 (0x4)  Subversion: 0x1250//LMP版本  
  18.         Manufacturer: Ericsson Technology Licensing (0)//作者  

(3)、启动蓝牙
hciconfig hci0 up
(4)、关闭蓝牙
hciconfig hci0 down
(5)、查看hci命令
hciconfighci0 commands 

(6)、显示OOB数据
Hciconfig hci0 oobdata


<think>好的,用户现在遇到了个关于蓝牙的问题,错误信息是“hci0: security requested but not available”。我需要分析这个问题,并给出解决方案。首先,我应该回忆下Linux下蓝牙相关的常见错误。 这个错误通常和安全机制有关。可能用户在尝试进行某种需要安全验证的操作,比如配对或连接设备,但系统缺少必要的支持。可能的原因包括缺少安全协议的支持、权限问题,或者蓝牙服务配置不正确。 首先,我应该考虑权限问题。Linux上的蓝牙操作通常需要root权限或者用户属于特定的组,比如bluetooth组。用户可能没有正确配置权限,导致无法访问安全功能。需要检查用户是否以root身份运行命令,或者是否将用户加入了bluetooth组,并重新登录生效。 接下来,检查BlueZ的版本是否过旧。旧版本的BlueZ可能不支持某些安全协议,比如SSP(Secure Simple Pairing)。建议用户升级BlueZ到最新版本,并确认相关服务是否正常运行,比如bluetooth.service。 另外,检查安全模式设置是否正确。使用hciconfig查看hci0的安全设置,可能需要启用安全模式,比如使用“hciconfig hci0 ssp 1”来开启SSP支持。还有可能需要配置IO能力,比如设置设备为KeyboardOnly或DisplayYesNo,具体取决于配对方式。 硬件兼容性也是个因素。某些蓝牙适配器可能不支持所需的安全功能,尤其是较旧的硬件。用户可能需要检查硬件规格,或者尝试更换适配器。 还有可能系统缺少必要的加密算法或内核模块。需要确保加密相关的模块如ecb、aes等已加载,可以通过lsmod检查,并使用modprobe加载缺失的模块。 此外,用户可能在运行某些命令时没有停止默认的蓝牙服务,导致冲突。建议停止bluetooth.service后再尝试操作,或者检查是否有其他进程占用设备。 最后,如果问题依旧,可能需要查看系统日志(如journalctl -u bluetooth)来获取更详细的错误信息,帮助进步诊断。 总结下来,解决步骤可能包括:检查权限、升级BlueZ、配置安全模式、检查硬件支持、加载内核模块、停止冲突服务,以及查看日志。需要将这些步骤清晰地传达给用户,并建议他们逐尝试,直到问题解决。</think>$\textcolor{blue}{[问题分析]}$ 当在Linux系统中操作蓝牙设备时出现 "hci0: security requested but not available" 错误,通常表示以下原因之: $$\text{安全协议缺失 + 权限配置问题 + 服务兼容性冲突}$$ $\textcolor{blue}{[详细解决方案]}$ 1. **内核模块检查** ```bash lsmod | grep -E 'bluetooth|btusb|bnep' ``` - 如果缺少关键模块,执行: ```bash sudo modprobe bluetooth btusb bnep ``` 2. **安全协议配置** 使用`hciconfig`调整安全设置: ```bash sudo hciconfig hci0 ssp 1 # 启用Secure Simple Pairing(SSP) sudo hciconfig hci0 encrypt # 强制启用加密 ``` 3. **权限修复** ```bash sudo usermod -aG bluetooth $USER # 将当前用户加入蓝牙组 sudo setcap 'cap_net_raw,cap_net_admin+eip' /path/to/your_program # 对特定程序授权 ``` 4. **BlueZ版本验证** ```bash bluetoothd -v # 要求版本≥5.50 sudo apt-get install bluez bluez-tools # Ubuntu/Debian更新命令 ``` 5. **服务冲突处理** 停止系统蓝牙服务后手动控制: ```bash sudo systemctl stop bluetooth.service sudo hciconfig hci0 up ``` 6. **安全模式设置实验** 尝试不同安全模式(在`bluetoothctl`中操作): ```bash agent KeyboardOnly # 适用于需要输入PIN码的场景 default-agent trust 00:11:22:33:44:55 # 目标设备MAC地址 ``` $\textcolor{blue}{[典型应用场景]}$ - **BLE配对失败** 当使用`gatttool`连接设备时出现该错误,需组合使用: ```bash sudo hciconfig hci0 leadv # 先停止广播 sudo gatttool -b <MAC> -I --sec-level=high ``` - **HFP协议连接问题** 对于语音网关类设备,需额外加载协议栈: ```bash sudo apt-get install pulseaudio-module-bluetooth pactl load-module module-bluetooth-discover ``` $\textcolor{blue}{[深度排查工具]}$ 1. **协议层诊断** ```bash sudo btmon -w debug_log.txt # 开启蓝牙监控 ``` 2. **内核调试** ```bash dmesg | grep -i bluetooth ``` 3. **安全策略验证** ```bash busctl call org.bluez /org/bluez/hci0 org.bluez.Adapter1 GetDiscoveryFilters ``` $\textcolor{blue}{[硬件相关注意]}$ 1. CSR芯片需加载特殊固件: ```bash sudo apt-get install bluez-firmware ``` 2. Intel无线网卡需更新固件: ```bash sudo apt-get install intel-microcode ``` $\textcolor{blue}{[最终验证]}$ 成功标志:执行以下命令不再报错 ```bash sudo l2ping -c 4 <DEVICE_MAC> # 测试基础连接 bluetoothctl pair <MAC> # 测试配对流程 ``` $\textcolor{red}{[补充说明]}$ 如果问题仍未解决,建议检查蓝牙芯片具体型号的官方文档,部分老款芯片(如BCM2035)确实存在安全协议支持不完整的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值