关键词: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实施和经常使用的更多相关文章

  1. S5PV210之Sate210-F DIY硬件,移植uboot,kernel,android 活动现在已经进入实施阶段吗,欢迎广大网友参与 !

    大家一起来diy 超低价四核的exynos4412或者Cortex A8S5pv210开源开发板 商业版Sate210已经完成了好久了.Sate4412 也已经出来.但是这两个接口非常全,主要是针对企 ...

  2. Android发展的一个重要方面Makefile分析

    Android发展的一个重要方面Makefile分析 随着移动互联网的发展,移动开发也越来越吃香了.眼下最火的莫过于android.android是什么就不用说了,android自从开源以来,就受到非 ...

  3. 二维码合成,将苹果和安卓(ios和android)合成一个二维码,让用户扫描一个二维码就可以分别下载苹果和安卓的应用

    因为公司推广的原因,没有合适的将苹果和安卓(ios和android)合成一个二维码的工具. 因为这个不难,主要是根据浏览器的UA进行判断,所以就自己开发了一个网站 网站名称叫:好推二维码  https ...

  4. Android 如何判断一个应用在运行(转)

    Android 如何判断一个应用在运行  在一个应用中,或一个Service .Receiver中判断一个应用是否正在运行,以便进行一些相关的处理. 这个时候我们需要得到一个ActivityManag ...

  5. android studio 导入一个已有的android studio project作为lib使用

    android studio 导入一个已有的android studio project作为lib使用 新项目来了. 需要搭建框架. android studio对我来说还是很陌生,之前一个项目在同事 ...

  6. Android Studio新建一个HelloWorld 程序(App)

    Android Studio新建一个HelloWorld程序(App) 新建 或者直接启动程序(注:如果已有程序,此方法会直接打开最近一次关闭从程序) 更改App名 选择App运行平台 选择模板 更改 ...

  7. android 自己创建一个凝视模板

    android  自己创建一个凝视模板 作为一名程序猿 不仅要有一个写代码的能力,养成一个良好的编写习惯也是非常重要的. 今天给大家具体介绍一下怎样创建凝视模板,给每一个类和方法都自己手动去凝视信息也 ...

  8. Android下实现一个简单的计算器源码

    下面的内容是关于Android下实现一个简单的计算器的内容. import android.app.Activity; import android.os.Bundle;import android. ...

  9. [android] android下创建一个sqlite数据库

    Sqlite数据库是开源的c语言写的数据库,android和iphone都使用的这个,首先需要创建数据库,然后创建表和字段,android提供了一个api叫SQLiteOpenHelper数据库的打开 ...

随机推荐

  1. dmalloc在嵌入式的开发板上的应用

    下面是我实际在开发环境里面做的dmalloc移植时候的一些随笔 配置PC的dmalloc环境1. 首先把源码包打开,进入dmalloc文件夹2. ./configure 配置Makefile,我是加了 ...

  2. ssl 内存泄露

    http://i.mtime.com/chevalier/blog/1824652/ openssl内存分配 chevalier 发布于: 2009-04-20 10:31  openssl内存分配  ...

  3. ReentrantLock Condition await signal 专题

    Condition的执行方式,是当在线程T1中调用await方法后,线程T1将释放锁,并且将自己阻塞,等待唤醒, 线程T2获取到锁后,开始做事,完毕后,调用Condition的signal方法,唤醒线 ...

  4. QT学习记录之控件布局

    作者:朱金灿 来源:http://blog.csdn.net/clever101 想到控件布局就会想到Windows编程中要实现对话框上的控件的合理布局是一件多么艰难的事情.对此QT提出了一个很方便的 ...

  5. 【社交分享SDK】ShareSDK for Android 2.5.9已经公布

    ShareSDK for Android 2.5.9已经公布 版本号:V2.5.9  2015-3-19 1.升级Dropbox对API接口的调用.包含授权.获取用户信息,分享三个接口 2.升级Kak ...

  6. 最新国内外可用SVN托管仓库有哪些

    最新国内外可用SVN托管仓库哪些 一.总结 一句话总结:用SVNBucket和SourceForge 二.最新国内外可用SVN托管仓库推荐 这几年很多SVN托管平台都基本不维护或者直接关闭了,我翻遍了 ...

  7. 利用performSelectorInBackground和performSelectorOnMainThread实现多线程

    NSObject类的performSelectorOnMainThread和performSelectorInBackground能够实现简单的多线程编程技术 1.- (void)performSel ...

  8. Expression Blend 的点滴(4)--创建类似iPhone屏幕锁控件(上)

    原文:Expression Blend 的点滴(4)--创建类似iPhone屏幕锁控件(上) 本篇文章,最终效果图:  当然,不只是一个UI而已,如果只是一张图片,那专业的设计师能做出更出色的效果.在 ...

  9. Git远程操作具体解释

    Git是眼下最流行的版本号管理系统,学会Git差点儿成了开发人员的必备技能. Git有非常多优势,当中之中的一个就是远程操作非常简便.本文具体介绍5个Git命令,它们的概念和使用方法,理解了这些内容. ...

  10. 数组replaceObjectAtIndex

    执行replaceObjectAtIndex方法前提是_temp_Array必须是可变数组 [_temp_Array replaceObjectAtIndex:2 withObject:tempDat ...