Android blueZ HCI(一):hciconfig实现及常用方法
来源:互联网 发布:张世杰 知乎 编辑:程序博客网 时间:2024/06/05 11:08
关键词:hciconfighcitool hcidump
作者:xubin341719(欢迎转载,请注明作者,请尊重版权,谢谢!)
欢迎指正错误,共同学习、共同进步!!
Android blueZ HCI(一):hciconfig实现及常用方法
Android blueZ hci(二):hcitool hcidump常用方法
一、Hciconfig
1、adb shell 下,hciconfig 执行文件的位
/system/xbin/hciconfig
相应目录下Android.mk文件,生成hciconfig
- #
- # hciconfig
- #
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES:= \
- csr.c \
- csr_h4.c \
- hciconfig.c
- ………………
- LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
- LOCAL_MODULE_TAGS := optional
- LOCAL_MODULE:=hciconfig
- include $(BUILD_EXECUTABLE)
2、hciconfig代码实现
idh.code\external\bluetooth\bluez\tools\hciconfig.c
main函数主要有两部分功能:main_options操作,命令的执行;
下面我们分两部分分析
- int main(int argc, char *argv[])
- {
- int opt, ctl, i, cmd=0;
- //(1)、hciconfig两个命main_options,help和all两个命令;
- while ((opt=getopt_long(argc, argv, "ah", main_options, NULL)) != -1) {
- switch(opt) {
- case 'a':
- all = 1;
- break;
- case 'h':
- default:
- usage();
- exit(0);
- }
- }
- //(2)、命令执行部分
- argc -= optind;
- argv += optind;
- optind = 0;
- /* Open HCI socket */
- if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) {
- perror("Can't open HCI socket.");
- exit(1);
- }
- if (argc < 1) {
- print_dev_list(ctl, 0);
- exit(0);
- }
- di.dev_id = atoi(argv[0] + 3);
- argc--; argv++;
- if (ioctl(ctl, HCIGETDEVINFO, (void *) &di)) {
- perror("Can't get device info");
- exit(1);
- }
- if (hci_test_bit(HCI_RAW, &di.flags) &&
- !bacmp(&di.bdaddr, BDADDR_ANY)) {
- int dd = hci_open_dev(di.dev_id);
- hci_read_bd_addr(dd, &di.bdaddr, 1000);
- hci_close_dev(dd);
- }
- while (argc > 0) {
- for (i = 0; command[i].cmd; i++) {
- if (strncmp(command[i].cmd, *argv, 5))
- continue;
- if (command[i].opt) {
- argc--; argv++;
- }
- command[i].func(ctl, di.dev_id, *argv);
- cmd = 1;
- break;
- }
- argc--; argv++;
- }
- if (!cmd)
- print_dev_info(ctl, &di);
- close(ctl);
- return 0;
- }
(1)、hciconfig两个命main_options,help和all两个命令
- int main(int argc, char *argv[])
- {
- int opt, ctl, i, cmd=0;
- //1)、hciconfig两个命main_options,help和all两个命令;
- while ((opt=getopt_long(argc, argv, "ah", main_options, NULL)) != -1) {//1)、main_options;
- switch(opt) {
- case 'a':
- all = 1;
- break;//2)、如果是all命令执行下去;
- case 'h':
- default:
- usage();//3)、如果是help命令打印出命令使用方法;
- exit(0);
- }
- }
- ………………
- }
1)、main_options;
while((opt=getopt_long(argc, argv, "ah", main_options, NULL)) != -1) {
getopt被用来解析命令行选项参数,getopt_long,解析命令参数支持长选项。即一对短横线、一个描述性选项名称,还可以包含一个使用等号连接到选项的参数。
http://blog.csdn.net/slmmlk2011_2/article/details/7964218中有详细介绍。
即:hciconfig–all
- main_options
- static struct option main_options[] = {
- { "help", 0, 0, 'h' },
- { "all", 0, 0, 'a' },
- { 0, 0, 0, 0 }
- };
2)、ops 解析出来数据,如果是a,打印出蓝牙相关信息
- case 'a':
- all = 1;
- break;
后面这部分和命令解析一起分析。
3)、如果是help命令,打印出命令使用方法;
- case 'h':
- default:
- usage();
- exit(0);
如果是help 执行usage这个函数。下面分析这个函数
idh.code\external\bluetooth\bluez\tools\hciconfig.c
- static void usage(void)
- {
- int i;
- printf("hciconfig - HCI device configuration utility\n");
- printf("Usage:\n"
- "\thciconfig\n"
- "\thciconfig [-a] hciX [command]\n");
- printf("Commands:\n");
- for (i=0; command[i].cmd; i++)
- printf("\t%-10s %-8s\t%s\n", command[i].cmd,
- command[i].opt ? command[i].opt : " ",
- command[i].doc);
- }
这个函数比较简单,就是不command[]结构体中的命令字符串打印出来:下面两个截图就一目了然了:
命令执行结果如下:
- static struct {
- char *cmd;//命令,比如hciconfig up;
- void (*func)(int ctl, int hdev, char *opt);//命令执行函数;
- char *opt;//
- char *doc;//命令描述
- } command[] = {
- { "up", cmd_up, 0, "Open and initialize HCI device" },
- { "down", cmd_down, 0, "Close HCI device" },
- { "reset", cmd_reset, 0, "Reset HCI device" },
- ………………
- }
使用up命令时,会调用到,cmd_up这个函数:
idh.code\external\bluetooth\bluez\tools\hciconfig.c
- static void cmd_up(int ctl, int hdev, char *opt)
- {
- /* Start HCI device */
- if (ioctl(ctl, HCIDEVUP, hdev) < 0) {
- if (errno == EALREADY)
- return;
- fprintf(stderr, "Can't init device hci%d: %s (%d)\n",
- hdev, strerror(errno), errno);
- exit(1);
- }
- }
(2)、命令执行部分
- Main()
- {
- ………………
- argc -= optind;
- argv += optind;
- optind = 0;
- /* Open HCI socket *///1)、打开HCI socket通信
- if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) {/
- perror("Can't open HCI socket.");
- exit(1);
- }
- if (argc < 1) {
- print_dev_list(ctl, 0);
- exit(0);
- }
- di.dev_id = atoi(argv[0] + 3);
- argc--; argv++;
- //2)、通过ioctl获取HCI驱动信息
- if (ioctl(ctl, HCIGETDEVINFO, (void *) &di)) {
- perror("Can't get device info");
- exit(1);
- }
- //3)、hci_test_bit bacmp
- if (hci_test_bit(HCI_RAW, &di.flags) &&
- !bacmp(&di.bdaddr, BDADDR_ANY)) {
- int dd = hci_open_dev(di.dev_id);
- hci_read_bd_addr(dd, &di.bdaddr, 1000);
- hci_close_dev(dd);
- }
- //4)命令执行
- while (argc > 0) {
- for (i = 0; command[i].cmd; i++) {
- if (strncmp(command[i].cmd, *argv, 5))
- continue;
- if (command[i].opt) {
- argc--; argv++;
- }
- command[i].func(ctl, di.dev_id, *argv);
- cmd = 1;
- break;
- }
- argc--; argv++;
- }
- if (!cmd)//没有相应的命令打印出
- print_dev_info(ctl, &di);
- //5)、关闭ctl,完成操作
- close(ctl);
- return 0;
- }
1)、打开HCI socket通信
- /* Open HCI socket */
- if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) {
- int socket(int domain, int type, int protocol);
参数说明:
domain:指明所使用的协议族,通常为PF_INET,表示TCP/IP协议;
type:参数指定socket的类型,基本上有三种:数据流套接字、数据报套接字、原始套接字
protocol:通常赋值"0"。
程序中蓝牙建立:
- damain:使用AF_BLUETOOTH;
- idh.code\3rdparty\bluetooth\Trout_BT\special\android\kernel\include\net\bluetooth\bluetooth.h
- #define AF_BLUETOOTH 31
- type: SOC_SEQPACKET,以Packet为单位读取,SOC_RAW:原始socket
- enum sock_type {
- SOCK_STREAM = 1,
- SOCK_DGRAM = 2,
- SOCK_RAW = 3,
- SOCK_RDM = 4,
- SOCK_SEQPACKET = 5,
- SOCK_DCCP = 6,
- SOCK_PACKET = 10,
- };
- protocol:使用相应建立的Socket的protocol,不同类型的入L2CAP、HCI、SCO……
- #define BTPROTO_L2CAP 0
- #define BTPROTO_HCI 1
- #define BTPROTO_SCO 2
- #define BTPROTO_RFCOMM 3
- #define BTPROTO_BNEP 4
- #define BTPROTO_CMTP 5
- #define BTPROTO_HIDP 6
- #define BTPROTO_AVDTP 7
if(ioctl(ctl, HCIGETDEVINFO, (void *) &di))
idh.code\3rdparty\bluetooth\Trout_BT\special\android\kernel\include\net\bluetooth\hci.h相关命令的定义
- #define HCIGETDEVLIST _IOR('H', 210, int)
- #define HCIGETDEVINFO _IOR('H', 211, int)
- #define HCIGETCONNLIST _IOR('H', 212, int)
- #define HCIGETCONNINFO _IOR('H', 213, int)
- #define HCIGETAUTHINFO _IOR('H', 215, int)
- di对应的数据结构
- static struct hci_dev_info di;
- struct hci_dev_info {
- __u16 dev_id;
- char name[8];
- bdaddr_t bdaddr;
- __u32 flags;
- __u8 type;
- __u8 features[8];
- __u32 pkt_type;
- __u32 link_policy;
- __u32 link_mode;
- __u16 acl_mtu;
- __u16 acl_pkts;
- __u16 sco_mtu;
- __u16 sco_pkts;
- struct hci_dev_stats stat;
- };
- if (hci_test_bit(HCI_RAW, &di.flags) &&
- !bacmp(&di.bdaddr, BDADDR_ANY)) {
- int dd = hci_open_dev(di.dev_id);
- hci_read_bd_addr(dd, &di.bdaddr, 1000);
- hci_close_dev(dd);
- }
判断di中相关参数。
hci_test_bit检测*addr的第nr位是否为1(*addr右起最低位为第0位)
- static inline int hci_test_bit(int nr, void *addr)
- {
- return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
- }
4)、命令执行,这部分是命令实现的部分
- while (argc > 0) {
- for (i = 0; command[i].cmd; i++) {
- if (strncmp(command[i].cmd, *argv, 5))//通过for循环比较第二个参数
- continue;
- if (command[i].opt) {
- argc--; argv++;
- }
- command[i].func(ctl, di.dev_id, *argv);//如果参数对应,就执行相应的命令函数
- cmd = 1;
- break;
- }
- argc--; argv++;
- }
- if (!cmd)//没有相应的命令打印出
- print_dev_info(ctl, &di);
a、如:if (strncmp(command[i].cmd, *argv, 5))// 通过for循环比较第二个参数
| 如命令:hciconfighci0 commands
argv 的值就为:commands字符串,如果5个字符相等。
b、如果对应,就执行相应的命令函数
- command[i].func(ctl, di.dev_id, *argv);
- { "commands", cmd_commands, 0, "Display supported commands" },
command[i].func = cmd_commands
对应commands 的实现函数cmd_commands函数的实现:
- static void cmd_commands(int ctl, int hdev, char *opt)
- {
- uint8_t cmds[64];
- char *str;
- int i, n, dd;
- dd = hci_open_dev(hdev);
- if (dd < 0) {
- fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
- hdev, strerror(errno), errno);
- exit(1);
- }
- if (hci_read_local_commands(dd, cmds, 1000) < 0) {
- fprintf(stderr, "Can't read support commands on hci%d: %s (%d)\n",
- hdev, strerror(errno), errno);
- exit(1);
- }
- print_dev_hdr(&di);
- for (i = 0; i < 64; i++) {
- if (!cmds[i])
- continue;
- printf("%s Octet %-2d = 0x%02x (Bit",
- i ? "\t\t ": "\tCommands:", i, cmds[i]);
- for (n = 0; n < 8; n++)
- if (cmds[i] & (1 << n))
- printf(" %d", n);
- printf(")\n");
- }
- str = hci_commandstostr(cmds, "\t", 71);
- printf("%s\n", str);
- bt_free(str);
- hci_close_dev(dd);
- }
- 这个是针对每个命令实现的具体函数。
- //5)、关闭ctl,完成操作
- close(ctl);
- return 0;
3、hciconfig命令常用方法:
(1)、帮助命令:查看hciconfig支持的命令和用法
hciconfig –h或者hciconfig --hlep
(2)、查看蓝牙相关信息
hciconfig –a
- root@android:/ # hciconfig -a
- hciconfig -a
- hci0: Type: BR/EDR Bus: UART//蓝牙的接口类型,这个是UART的,还有USB、PCI…………
- BD Address: 00:16:53:96:22:53 ACL MTU: 1021:8 SCO MTU: 120:10//蓝牙地址
- UP RUNNING PSCAN//命令状态
- RX bytes:2846 acl:0 sco:0 events:67 errors:0
- TX bytes:2034 acl:0 sco:0 commands:80 errors:0
- Features: 0xff 0xff 0x8d 0xfe 0x9b 0xbf 0x79 0x83
- Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3//支持数据包
- Link policy: RSWITCH HOLD SNIFF PARK
- Link mode: SLAVE ACCEPT//连接的类型,是主设备、从设备
- Name: 'sp8825c1'//蓝牙名称
- Class: 0x5a020c//蓝牙的类型
- Service Classes: Networking, Capturing, Object Transfer, Telephony//支持的类型
- Device Class: Phone, Smart phone
- HCI Version: 2.1 (0x4) Revision: 0x1250//HCI版本
- LMP Version: 2.1 (0x4) Subversion: 0x1250//LMP版本
- Manufacturer: Ericsson Technology Licensing (0)//作者
(3)、启动蓝牙
hciconfig hci0 up
(4)、关闭蓝牙
hciconfig hci0 down
(5)、查看hci命令
hciconfighci0 commands
(6)、显示OOB数据
Hciconfig hci0 oobdata
- Android blueZ HCI(一):hciconfig实现及常用方法
- Android blueZ HCI(一):hciconfig实现及常用方法
- Android blueZ HCI(一):hciconfig实现及常用方法
- Android blueZ HCI(一):hciconfig实现及常用方法
- Android blueZ HCI(二):hcitool hcidump常用方法
- Android blueZ HCI(二):hcitool hcidump常用方法
- Android blueZ HCI(二):hcitool hcidump常用方法
- hciconfig - HCI device configuration utility
- 蓝牙HCI剖析(一)
- 蓝牙HCI剖析(一)
- 蓝牙HCI剖析(一)
- hciconfig
- hciconfig
- android bluez
- android bluez
- Web服务及实现方法(一)
- 通过Bluez提供的Interface发送HCI Command
- 通过Bluez提供的Interface发送HCI Command
- 转自知呼:努力了七年却依旧被中产阶级家庭子女完爆,我该如何调整心态?
- 【问底】伍艺:一种基于Rsync算法的数据库备份方案设计
- MyBatis中出现Mapped Statements collection does not contain value异常解决方案
- 异步操作AsyncTask(一)从网络下载图片
- 大气压传感器基础知识
- Android blueZ HCI(一):hciconfig实现及常用方法
- mkinitramfs命令详解
- C#一句话判断两个List<T>是否相等
- Linux内核中timer_list定时器的使用
- GitHub 给安全行业的四大启示
- Java中关于线程的总结
- 关于ftp文件系统的创建
- 数据库并发事务控制 三:mysql数据库MVCC
- visio 2010 密钥