Android blueZ HCI(一个):hciconfig实施和经常使用
关键词: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[]结构体中的命令字符串打印出来:以下两个截图就一目了然了:
命令运行结果例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveHViaW4zNDE3MTk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
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, 0, "Open and initialize HCIdevice" },为例说明
使用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
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相关命令的定义
#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;
};
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);
}
推断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);
c、假设是commands命令:对应command[]结构体中的数组
{ "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
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveHViaW4zNDE3MTk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
(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实施和经常使用的更多相关文章
- S5PV210之Sate210-F DIY硬件,移植uboot,kernel,android 活动现在已经进入实施阶段吗,欢迎广大网友参与 !
大家一起来diy 超低价四核的exynos4412或者Cortex A8S5pv210开源开发板 商业版Sate210已经完成了好久了.Sate4412 也已经出来.但是这两个接口非常全,主要是针对企 ...
- Android发展的一个重要方面Makefile分析
Android发展的一个重要方面Makefile分析 随着移动互联网的发展,移动开发也越来越吃香了.眼下最火的莫过于android.android是什么就不用说了,android自从开源以来,就受到非 ...
- 二维码合成,将苹果和安卓(ios和android)合成一个二维码,让用户扫描一个二维码就可以分别下载苹果和安卓的应用
因为公司推广的原因,没有合适的将苹果和安卓(ios和android)合成一个二维码的工具. 因为这个不难,主要是根据浏览器的UA进行判断,所以就自己开发了一个网站 网站名称叫:好推二维码 https ...
- Android 如何判断一个应用在运行(转)
Android 如何判断一个应用在运行 在一个应用中,或一个Service .Receiver中判断一个应用是否正在运行,以便进行一些相关的处理. 这个时候我们需要得到一个ActivityManag ...
- android studio 导入一个已有的android studio project作为lib使用
android studio 导入一个已有的android studio project作为lib使用 新项目来了. 需要搭建框架. android studio对我来说还是很陌生,之前一个项目在同事 ...
- Android Studio新建一个HelloWorld 程序(App)
Android Studio新建一个HelloWorld程序(App) 新建 或者直接启动程序(注:如果已有程序,此方法会直接打开最近一次关闭从程序) 更改App名 选择App运行平台 选择模板 更改 ...
- android 自己创建一个凝视模板
android 自己创建一个凝视模板 作为一名程序猿 不仅要有一个写代码的能力,养成一个良好的编写习惯也是非常重要的. 今天给大家具体介绍一下怎样创建凝视模板,给每一个类和方法都自己手动去凝视信息也 ...
- Android下实现一个简单的计算器源码
下面的内容是关于Android下实现一个简单的计算器的内容. import android.app.Activity; import android.os.Bundle;import android. ...
- [android] android下创建一个sqlite数据库
Sqlite数据库是开源的c语言写的数据库,android和iphone都使用的这个,首先需要创建数据库,然后创建表和字段,android提供了一个api叫SQLiteOpenHelper数据库的打开 ...
随机推荐
- angular组件间的信息传递
原文 https://www.jianshu.com/p/82207f2249c1 大纲 1.父组件向子组件传递信息:通过属性 2.子组件向父组件传递信息:通过事件 3.父组件获取子组件的信息:通过调 ...
- window下利用navicat访问Linux下的mariadb数据库
1.再Linux上成功安装mariadb数据库后,不管是在dos(敲命令mysql -h192.168.136.8 -uroot -p)下或者是navicat(创建连接)下连接mariadb数据库,会 ...
- 多校 hdu
欢迎參加--每周六晚的BestCoder(有米!) Solve this interesting problem Time Limit: 2000/1000 MS (Java/Others) M ...
- ios开发网络学习五:输出流以及文件上传
一:输出流 #import "ViewController.h" @interface ViewController ()<NSURLConnectionDataDelega ...
- 修改QList中的item(使用下标([index])才可以获得可修改的item的引用)
QList算是最常用的集合了,今儿偶然间需要修改QList中的值,结果郁闷了.QList中提供了replace函数来替换item,但不是修改.而at().value()操作均返回的是const的ite ...
- [RxJS] Use RxJS concatMap to map and concat high order observables
Like switchMap and mergeMap, concatMap is a shortcut for map() followed by a concatAll(). In this le ...
- php利用反射机制查找类和方法的所在位置
//参数1是类名,参数2是方法名 $func = new ReflectionMethod('UnifiedOrder_pub', 'getPrepayId'); //从第几行开始 $start = ...
- 微信小程序从零开始开发步骤(二)
上一章注册完小程序,添加新建的项目,大致的准备开发已经完成,本章要分享的是要创建一个简单的页面了,创建小程序页面的具体几个步骤: 1. 在pages 中添加一个目录 选中page,右击鼠标,从硬盘打开 ...
- HDU 树型dp
HDU 4123 Bob's Race 题意:定义每个点的值为它到树上最远点的距离,每次询问q,回答最长的极值差小于等于q且编号连续的一段点的长度. 题解:求距离两次dp,求极值ST表+尺取法. HD ...
- zookeeper 半数可用/选举机制
1.半数可用机制,半数可用指的是zk集群中一半以上的机器正常时集群才能正常工作 已经启动了hadoop002(follower),hadoop003(leader) 下面停止hadoop002 在ha ...