bluez源码都是些什么java文件管理系统源码干什么用的

网站已改版,请使用新地址访问:
bluez-4.0 这是Linux环境下的蓝牙源代码,版本为4.0,可以共 爱好者和嵌入式开发者研究使用 Internet-Socket-Network 277万源代码下载-
网站已改版,请使用新地址访问:
&文件名称: bluez-4.0
& & & & &&]
&&所属分类:
&&开发工具: Unix_Linux
&&文件大小: 1006 KB
&&上传时间:
&&下载次数: 75
&&提 供 者:
&详细说明:这是Linux环境下的蓝牙源代码,版本为4.0,可以共Linux爱好者和嵌入式开发者研究使用。-This is the Linux environment Bluetooth source code, version 4.0, can be a total of Linux enthusiasts and embedded developers study.
文件列表(日期:~)(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&bluez-4.0&&.........\bluez-4.0&&.........\.........\&&.........\.........\aclocal.m4&&.........\.........\audio&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\asound.conf&&.........\.........\.....\audio-api.txt&&.........\.........\.....\audio.conf&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\Makefile.am&&.........\.........\.....\Makefile.in&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\.....\&&.........\.........\&&.........\.........\&&.........\.........\&&.........\.........\ChangeLog&&.........\.........\common&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\Makefile.am&&.........\.........\......\Makefile.in&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\compat&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\fakehid.txt&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\Makefile.am&&.........\.........\......\Makefile.in&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\......\&&.........\.........\&&.........\.........\&&.........\.........\&&.........\.........\configure&&.........\.........\&&.........\.........\&&.........\.........\&&.........\.........\cups&&.........\.........\....\&&.........\.........\....\
&[]:很好,推荐下载&[]:很好,推荐下载
&近期下载过的用户:
&相关搜索:
&输入关键字,在本站277万海量源码库中尽情搜索:
&[] - 基于TCP的客户端和服务器端的套接字编程,对初学者有用,里面有截图和使用说明
&[] - 介绍一个异步通信的socket类,VC++60编译通过。
&[] - linux下NAT协议完整源代码,并且有详细的分析说明。
&[] - linux下多线程下载的应用程序源码,希望对大家学习多线程下载有用。
&[] - upnp协议实现的源代码,对于学习或是开发嵌入式互联网产品的朋友有帮助.解压时请去掉文件名最后面的.gz
&[] - 本源码为windows下hilscher公司profibus接口的驱动 对基于嵌入式及windows平台接口驱动开发均有很大用处。
&[] - bluez蓝牙协议栈源码,开发蓝牙模块参考必备
&[] - 一个用于手机蓝牙通讯的程序,其中包含了源码和编译过的程序,希望对你的工作会有帮助
&[] - 以前做QT编程时留下的QT4中文资料,从基础讲起,非常适合嵌入式图形界面编程的初学者!
&[] - 台湾智达蓝牙方案图纸
pdf格式原理图 详细,l2cap,sdp和rfcomm的一些应用编程。
一、HCI层协议概述
1、HCI Command Packets
详见bluez源码:lib/hci.h
/* Link Control */
#define OGF_LINK_CTL
#define OCF_INQUIRY
#define OCF_INQUIRY_CANCEL
#define OCF_PERIODIC_INQUIRY
#defineOCF_EXIT_PERIODIC_INQUIRY
#define OCF_CREATE_CONN
#define OCF_DISCONNECT
#define OCF_ADD_SCO
/* Link Policy */
#define OGF_LINK_POLICY
#define OCF_HOLD_MODE
#define OCF_SNIFF_MODE
#define OCF_EXIT_SNIFF_MODE 0x0004
#define OCF_PARK_MODE
#define OCF_EXIT_PARK_MODE
#define OCF_QOS_SETUP
#define OCF_ROLE_DISCOVERY
#define OCF_SWITCH_ROLE
#define OCF_READ_LINK_POLICY
#defineOCF_WRITE_LINK_POLICY
#defineOCF_READ_DEFAULT_LINK_POLICY
#defineOCF_WRITE_DEFAULT_LINK_POLICY
#defineOCF_FLOW_SPECIFICATION
#define OCF_SNIFF_SUBRATING
/* Host Controller andBaseband */
#define OGF_HOST_CTL
#define OCF_SET_EVENT_MASK
#define OCF_RESET
#define OCF_SET_EVENT_FLT
#define OCF_FLUSH
#define OCF_READ_PIN_TYPE
#define OCF_WRITE_PIN_TYPE
#defineOCF_CREATE_NEW_UNIT_KEY
#defineOCF_READ_STORED_LINK_KEY
#defineOCF_WRITE_STORED_LINK_KEY
#defineOCF_DELETE_STORED_LINK_KEY
#defineOCF_CHANGE_LOCAL_NAME
#define OCF_READ_LOCAL_NAME
#defineOCF_READ_CONN_ACCEPT_TIMEOUT
#defineOCF_WRITE_CONN_ACCEPT_TIMEOUT
#defineOCF_READ_PAGE_TIMEOUT
/* InformationalParameters */
#define OGF_INFO_PARAM
#defineOCF_READ_LOCAL_VERSION
#defineOCF_READ_LOCAL_COMMANDS
#defineOCF_READ_LOCAL_FEATURES
#defineOCF_READ_LOCAL_EXT_FEATURES 0x0004
#define OCF_READ_BUFFER_SIZE
#defineOCF_READ_COUNTRY_CODE
#define OCF_READ_BD_ADDR
#define OCF_READ_DATA_BLOCK_SIZE
/* Status params */
#define OGF_STATUS_PARAM 0x05
#defineOCF_READ_FAILED_CONTACT_COUNTER
#defineOCF_RESET_FAILED_CONTACT_COUNTER
#defineOCF_READ_LINK_QUALITY
#define OCF_READ_RSSI
#define OCF_READ_AFH_MAP
#define OCF_READ_CLOCK
#defineOCF_READ_LOCAL_AMP_INFO 0x0009
#defineOCF_READ_LOCAL_AMP_ASSOC
#defineOCF_WRITE_REMOTE_AMP_ASSOC
2、HCI ACL Data Packets
3、HCI synchronous (SCO and eSCO) DataPackets
4、HCI Event Packet
#define EVT_INQUIRY_COMPLETE
#define EVT_INQUIRY_RESULT
#define EVT_CONN_COMPLETE
#define EVT_CONN_REQUEST
#define EVT_DISCONN_COMPLETE
#define EVT_AUTH_COMPLETE
#defineEVT_REMOTE_NAME_REQ_COMPLETE
#define EVT_ENCRYPT_CHANGE
HCI Event分3种:Command complete Event,Command States Event,Command Subsequently Completed.
1)、Command complete Event: 如果Host发送的Command可以立刻有结果,则会发送此类
&&&& Event。也就是说,如果发送的Command只与本地Modules有关,不与remote设备打&&
&&&& 交道,则使用Command complete Event。例如:HCI_Read_Buffer_Size.
2)、Command States Event:如果Host发送的Command不能立刻得知结果,则发送此类&&&
&&&& Event。Host发送的Command执行要与Remote设备打交道,则必然无法立刻得知结
&&&& 果,所以会发送Command States Event.例如:
&HCI Connect。
3)、Command SubsequentlyCompleted:Command延后完成Event。例如:连接已建立。
例子:remote namerequest
从这里可以看出,如果Host发送的Command是与Remote device有关的,则会先发送Command States Event 。等动作真正完成了,再发送Command Subsequently Completed。
l2cap数据传输
一个l2cap包会按照规则先切割为多个HCI数据包。HCI数据包再通过HCI-usb这一层传递给USB设备。每个包又通过USB driver发送到底层。
二、HCI层的编程
HCI是沟通上层协议以及程序与底层硬件协议的通道。所以,通过HCI发送的Command都是上层协议或者应用程序发送给Bluetooth device的。它命令Bluetooth device(或其中的硬件协议)去做什么何种动作。
Socket基础概念:
使用函数socket()建立一个Socket,就如同你有一部电话。bind()则是把这个电话和某个电话号码(网络地址)对应起来。
类似的,我们可以把Host理解为一个房间,这个房间有多部电话(Dongle)。
当使用socket() 打开一个HCI protocol的socket,表明得到这个房间的句柄。HOST可能会有多个device。换句话说,这个房间可以有多个电话号码。所以HCI会提供一套指令去得到这些device。
得到Host上插入设备数目以及device信息
// 0. 分配一个空间给 hci_dev_list_req。这里面将放所有device信息。
structhci_dev_list_req *
structhci_dev_req *
structhci_dev_
if (!(dl = malloc(HCI_MAX_DEV * sizeof(structhci_dev_req) + sizeof(uint16_t)))) {
perror(&Can't allocate memory&);
dl-&dev_num = HCI_MAX_DEV;
dr = dl-&dev_
//1. 打开一个HCI socket.此socket相当于一个房间。
if ((ctl= socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) & 0) {
perror(&Can't open HCI socket.&);
// 2. 使用HCIGETDEVLIST,得到所有device的Device ID。存放在dl中。
if (ioctl(ctl, HCIGETDEVLIST, (void *) dl)& 0) {
perror(&Can't get device list&);
// 2. 使用HCIGETDEVLIST,得到所有device的Device ID。存放在dl中。
if (ioctl(ctl, HCIGETDEVLIST, (void *) dl)& 0) {
perror(&Can't get device list&);
device信息:
struct hci_dev_info {
uint16_t dev_
//Device ID
//device name
//device bdaddr
//device Flags:如:UP,RUNING,Down等。
//device 连接方式:如USB,PC Card,UART,RS232等。
uint8_t features[8];
uint32_t pkt_
uint32_t link_
uint32_t link_
uint16_t acl_
uint16_t acl_
uint16_t sco_
uint16_t sco_
//此device的数据信息,如发送多少个ACL Packet,正确多少,错误多少,等等。
UP和Down Bluetooth device:
ioctl(ctl, HCIDEVUP, hdev)
ioctl(ctl, HCIDEVDOWN, hdev)
ctl:为使用socket(AF_BLUETOOTH,SOCK_RAW, BTPROTO_HCI)打开的Socket.
hdev: Device ID.(所以上面的Socket不需要bind,因为这边指定了)
&BlueZ提供的HCI编程接口一(针对本地device的API系列)
1 打开一个HCI Socket
inthci_open_dev(int dev_id):
这个function用来打开一个HCI Socket。它首先打开一个HCI protocol的Socket(房间),并将此Socket与device ID=参数dev_id的device绑定起来。只有bind后,它才将Socket句柄与device对应起来。
注意,所有的HCI Command发送之前,都需要使用 hci_open_dev打开并绑定。
2 关闭一个HCI Socket:
inthci_close_dev(int dd) //简单的关闭使用hci_open_dev打开的Socket。
3& 向HCI Socket(对应一个Dongle)发送 request
inthci_send_req(int dd, struct hci_request *r, int to)
BlueZ提供这个function非常有用,它可以实现一切Host向Modules发送Command的功能。
参数1:HCI Socket。
参数2:Command内容。
参数3:以milliseconds为单位的timeout。
下面详细解释此function和用法:
当应用程序需要向Dongle(对应为一个bind后的Socket)发送Command时,调用此function。其中,
参数一dd对应一个使用hci_open_dev()打开的Socket(Dongle)。
参数三to则为等待Dongle执行并回复命令结果的timeout.以毫秒为单位。
参数二hci_request * r 最为重要,首先看它的结构:
structhci_request {
//Opcode Group
//Opcode Command
//此Command产生的Event类型。
* //Command 参数
//Command参数长度
//Response 参数
//Response 参数长度
ogf,ocf不用多说,对应前面的图就明白这是Group Code和Command Code。这两项先确定下来,然后可以查HCI Spec。察看输入参数(cparam)以及输出参数(rparam)含义。至于他们的结构以及参数长度,则在~/include/net/bluetooth/hci.h中有定义。
至于event.如果设置,它会被setsockopt设置于Socket。
例1:得到某个连接的Policy Setting.
HCI Spec以及~/include/net/bluetooth/hci.h中均可看到,OGF=OGF_LINK_POLICY(0x02).OCF=OCF_READ_LINK_POLICY(0x0C).
因为这个Command用来读取某个ACL连接的Policy Setting。所以输入参数即为此连接Handle。返回参数则包含3部分,status(Command是否顺利执行), handle(连接Handle)。 policy(得到的policy值)
这就又引入了一个新问题,如何得到某个ACL连接的Handle。
可以使用ioctlHCIGETCONNINFO得到ACL 连接Handle。
ioctl(dd, HCIGETCONNINFO,(unsigned long) cr);
Connect_handle =htobs(cr-&conn_info-&handle);
所以完整的过程如下:
struct hci_requestHCI_R
read_link_policy_cp Command_P
read_link_policy_rp Response_P
// 1.得到ACL Connect Handle
if (ioctl(dd,HCIGETCONNINFO, (unsigned long) cr) & 0)
return -1;
Connect_handle = htobs(cr-&conn_info-&handle);
memset(&HCI_Request, 0,sizeof(HCI_Request));
memset(&Command_Param, 0 ,sizeof(Command_Param));
memset(&Response_Param, 0 ,sizeof(Response_Param));
// 2.填写Command输入参数
Command_Param.handle = Connect_
HCI_Request.ogf = OGF_LINK_POLICY;
//Command组ID
HCI_Request.ocf = OCF_READ_LINK_POLICY;//Command ID
HCI_Request.cparam = &Command_P
HCI_Request.clen = READ_LINK_POLICY_CP_SIZE;
HCI_Request.rparam = &Response_P
HCI_Request.rlen = READ_LINK_POLICY_RP_SIZE;
if (hci_send_req(dd,&HCI_Request, to) & 0)
perror(&\nhci_send_req()&);
return -1;
//如果返回值状态不对
if (Response_Param.status) {
return -1;
//得到当前policy
*policy = Response_Param.&
4 几个更基础的function
static inline void bacpy(bdaddr_t*dst, const bdaddr_t *src) //bdaddr copy
static inline intbacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)//bdaddr 比较
5 得到指定Dongle BDAddr
int hci_read_bd_addr(int dd,bdaddr_t *bdaddr, int to);
参数1:HCI Socket,使用hci_open_dev()打开的Socket(Dongle)。
参数2:输出参数,其中会放置bdaddr.
参数3:以milliseconds为单位的timeout.
6 读写device Name
int hci_read_local_name(intdd, int len, char *name, int to)
int hci_write_local_name(intdd, const char *name, int to)
参数1:HCI Socket,使用hci_open_dev()打开的Socket(Dongle)。
参数2:读取或设置Name。
参数3:以milliseconds为单位的timeout.
注意:这里的Name与IOCTL HCIGETDEVINFO 得到hci_dev_info中的name不同。
7 得到HCI Version:
inthci_read_local_version(int dd, struct hci_version *ver, int to)
8 得到已经UP的device BDaddr
int hci_devba(int dev_id,bdaddr_t *bdaddr);
dev_id: Device ID.
bdaddr:输出参数,指定device如果UP, 则放置其BDAddr。
9 得到device Info
int hci_devinfo(int dev_id,struct hci_dev_info *di)
Device ID.
di: 此device信息。
出错返回 -1。
注意,这个Function的做法与3.0的方法完全一致。
10 从hciX中得到X
int hci_devid(const char*str)
str: 类似 hci0这样的字串。
如果hciX对应的Device ID(X)是现实存在且UP。则返回此设备Device ID。
11得到BDADDR不等于参数bdaddr的Device ID
int hci_get_route(bdaddr_t*bdaddr)
查找device,发现device Bdaddr不等于参数bdaddr的第一个device,则返回此 Device ID。所以,如果: int hci_get_route(NULL),则得到第一个可用的 Device ID。
12 将BDADDR转换为字符串
int ba2str(const bdaddr_t*ba, char *str)
将自串转换为BDADDR
int str2ba(const char *str,bdaddr_t *ba)
BlueZ提供的HCI编程接口二(针对Remote Device的API系列)
1& inquiry 远程Bluetooth Device
int hci_inquiry(int dev_id,int len, int nrsp, const uint8_t *lap, inquiry_info **ii, long flags)
hci_inquiry()用来命令指定的Dongle去搜索周围所有bluetooth device.并将搜索到的Bluetooth Device bdaddr 传递回来。
参数1:dev_id:指定Dongle Device ID。如果此值小于0,则会使用第一个可用的Dongle。
参数2:len: 此次inquiry的时间长度(每增加1,则增加1.25秒时间)
参数3:nrsp:此次搜索最大搜索数量,如果给0。则此值会取255。
参数4:lap:BDADDR中LAP部分,Inquiry时这块值缺省为0X9E8B33.通常使用NULL。则自动设置。
参数5:ii:存放搜索到Bluetooth Device的地方。给一个存放inquiry_info指针的地址,它会自动分配空间。并把那个空间头地址放到其中。
参数6:flags:搜索flags.使用IREQ_CACHE_FLUSH,则会真正重新inquiry。否则可能会传回上次的结果。
返回值是这次Inquiry到的Bluetooth Device 数目。
注意:如果*ii不是自己分配的,而是让hci_inquiry()自己分配的,则需要调用bt_free()来帮它释放空间。
2 得到指定BDAddr的reomte device Name
int hci_read_remote_name(intdd, const bdaddr_t *bdaddr, int len, char *name, int to)
参数1:使用hci_open_dev()打开的Socket。
参数2:对方BDAddr.
参数3:name 长度。
参数4:(out)放置name的位置。
参数5:等待时间。
3 读取连接的信号强度
int hci_read_rssi(int dd,uint16_t handle, int8_t *rssi, int to)
注意,所有对连接的操作,都会有一个参数,handle.这个参数是连接的Handle。前面讲过如何得到连接Handle的。
//scan是一个利用hci层协议 获得远程蓝牙设备的蓝牙地址和蓝牙昵称的函数;
int scan()
inquiry_info *ii = NULL;
int max_rsp, num_
int dev_id, sock, len,
char addr[19] = { 0 };
char name[248] = { 0 };
dev_id = hci_get_route(NULL);
printf(&/nhci%d is scanning....../n&,dev_id);
//dev_id = lc[scannum].
sock = hci_open_dev( dev_id );
if (dev_id & 0 || sock & 0)
system(&reboot&);
perror(&opening socket&);
bacpy(&src, BDADDR_ANY);
max_rsp = 255;
flags = IREQ_CACHE_FLUSH;
ii = (inquiry_info*)malloc(max_rsp * sizeof(inquiry_info));
num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii,flags);
if( num_rsp & 0 ) perror(&hci_inquiry&);
for (i = 0; i & num_ i++)
ba2str(&(ii+i)-&bdaddr, addr);
memset(name, 0, sizeof(name));
if (sdp_get_channel_opush(&src, &(ii+i)-&bdaddr,&c))
//printf(&/n%d/n&,c);
if(c&0)addadr(addr,c);
//此处是我在做项目中做的一个与应用程序连接的接口函数,功能是完成远程蓝牙设备的地址和文件传输通道号添加到我自己建的地址列表中.
//printf(&chinal=%d/n&,c);
// if (hci_read_remote_name(sock, &(ii+i)-&bdaddr,sizeof(name), name, 0) & 0)
// strcpy(name, &[unknown]&);
// printf(&%s %s/n&, addr, name);
free( ii );
close( sock );
//sdp_get_channel_opush,这是一个我自己编写的通过 hci获得的远程蓝牙地址和初始化为零的channel来获取远程蓝牙设备有无文件传输功能,并获得文件传输通道的过程。
intsdp_get_channel_opush(bdaddr_t *src, bdaddr_t *dst, int *channel)
sdp_session_t *
sdp_list_t *search, *attrs, *
/* build search request */
sdp_uuid16_create(&service, OBEX_OBJPUSH_SVCLASS_ID);
search = sdp_list_append(0, &service);
attr = SDP_ATTR_PROTO_DESC_LIST;
attrs = sdp_list_append(NULL, &attr);
/* connect */
session = sdp_connect(src, dst, SDP_RETRY_IF_BUSY);
if (!session) return(-1);
/* send request */
err = sdp_service_search_attr_req(session, search,SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
/* close connection */
sdp_close(session);
printf(&sdp_service_search_attr_req-return=%d/n&,err);
if (err) return(0);
/* get rfcomm channel */
for(; rsp = rsp-&next)
sdp_record_t *rec = (sdp_record_t *) rsp-&
sdp_list_t *
if (!sdp_get_access_protos(rec, &protos))
int ch = sdp_get_proto_port(protos, RFCOMM_UUID);
printf(&channel=%d/n&,ch);
if (ch & 0)
*channel =
return(1);
return(0);
一、L2CAP协议简介
L2CAP 基于 通道(channel) 的概念。 通道 (Channel) 是位于基带 (baseband) 连接之上的逻辑连接。每个通道以多对一的方式绑定一个单一协议(single protocol)。多个通道可以绑定同一个协议,但一个通道不可以绑定多个协议。每个在通道里接收到的 L2CAP 数据包被传到相应的上层协议。 多个通道可共享同一个基带连接。
也就是说,所有L2CAP数据均通过HCI传输到Remote Device。且上层协议的数据,大都也通过L2CAP来传送。
L2CAP可以发送Command。例如连接,断连等等。其命令格式如下
Command format:
例子:CONNECTIONREQUEST (CODE 0x02)
Identifier:请求的匹配响应。
Source CID:Set up sourceconnection channel identifier
PSM(Protocol/ServiceMultiplexer):比较需要注意,L2CAP 使用L2CAP连接请求(ConnectionRequest )命令中的PSM字段实现协议复用。L2CAP可以复用发给上层协议的连接请求,这些上层协议包括服务发现协议SDP(PSM = 0x0001)、RFCOMM(PSM = 0x0003)和电话控制(PSM = 0x0005)等。
TCS-BIN-CORDLESS
HID_Control
HID_Interrupt
AVCTP_Browsing
UDI_C-Plane
二、L2CAP编程方法
几乎所有协议的连接,断连,读写都是用L2CAP连接来做的。
1.创建L2CAP Socket:
socket(PF_BLUETOOTH,SOCK_RAW, BTPROTO_L2CAP);
domain=PF_BLUETOOTH,type可以是多种类型。protocol=BTPROTO_L2CAP.
// Bindto local address
memset(&addr, 0, sizeof(addr));
addr.l2_family = AF_BLUETOOTH;
bacpy(&addr.l2_bdaddr, &bdaddr);//bdaddr为本地Dongle BDAddr
if (bind(sk, (struct sockaddr *) &addr,sizeof(addr)) & 0) {
perror(&Can't bind socket&);
memset(&addr,0, sizeof(addr));
addr.l2_family= AF_BLUETOOTH;
bacpy(addr.l2_bdaddr,src);
addr.l2_psm=
if (connect(sk, (struct sockaddr *) &addr,sizeof(addr)) & 0) {
perror(&Can't connect&);
memset(&addr,0, sizeof(addr));
addr.l2_family= AF_BLUETOOTH;
bacpy(addr.l2_bdaddr,src);
addr.l2_psm=
if (connect(sk, (struct sockaddr *) &addr,sizeof(addr)) & 0) {
perror(&Can't connect&);
4. 发送数据到Remote Device:
send()或write()都可以。
5. 接收数据:
revc() 或read()
Bluetooth设备的状态
之前HCI编程时,是用 ioctl(HCIGETDEVINFO)得到某个Device Info(hci_dev_info).其中flags当时解释的很简单。其实它存放着BluetoothDevice(例如:USB BluetoothDongle)的当前状态:
其中,UP,Down状态表示此Device是否启动起来。可以使用ioctl(HCIDEVUP)等修改这些状态。
另外:就是Inquiry Scan,PAGE Scan这些状态:
Sam在刚开始自己做L2CAP层连接时,使用另一台Linux机器插USB BluetoothDongle作Remote Device。怎么也没法使用inquiry扫描到remote设备,也没法连接remote设备,甚至无法使用l2ping ping到remote设备。觉得非常奇怪,后来才发现Remote Device状态设置有问题。没有设置PSCAN和ISCAN。
InquiryScan状态表示设备可被inquiry. PageScan状态表示设备可被连接。
#hciconfighci0 iscan
#hciconfighci0 pscan
或者:#hciconfighci0 piscan
就可以设置为PSCAN或者iSCAN状态了。
编程则可以使用ioctl(HCISETSCAN). dev_opt = SCAN_INQUIRY;dr.dev_opt = SCAN_PAGE;dr.dev_opt = SCAN_PAGE |SCAN_INQUIRY;
则可以inquiry或者connect了。
例一:发送SignalingPacket:
SignalingCommand是2个Bluetooth实体之间的L2CAP层命令传输。所以得SignalingCommand使用CID 0x0001.
多个Command可以在一个C-frame(control frame)中发送。
如果要直接发送SignalingCommand.需要建立SOCK_RAW类型的L2CAP连接Socket。这样才有机会自己填充Command Code,Identifier等。
发送signalingCommand以及接收Response的简单例子:
#include&stdio.h&
#include&sys/types.h&
#include&sys/socket.h&
#include&stdlib.h&
#include&poll.h&
#include&bluetooth/bluetooth.h&
#include&bluetooth/hci.h&
#include&bluetooth/hci_lib.h&
#include&bluetooth/l2cap.h&
intmain(int argc,
char** argv)
int l2_sck = 0;
int iRel = 0;
struct sockaddr_l2 local_l2_
struct sockaddr_l2 remote_l2_
char str[24] ={0};
int len = 0;
int size = 50;
char* send_
char* recv_
int i = 0;
int id = 1; //不要为0
send_buf = malloc(L2CAP_CMD_HDR_SIZE +size);
recv_buf = malloc(L2CAP_CMD_HDR_SIZE +size);
if(argc & 2)
printf(&\n%s&bdaddr&\n&, argv[0]);
// create l2cap raw socket
l2_sck = socket(PF_BLUETOOTH, SOCK_RAW,BTPROTO_L2CAP); //创建L2CAPprotocol的RAW Packet
if(l2_sck & 0)
perror(&\nsocket:&);
memset(&local_l2_addr, 0, sizeof(structsockaddr_l2));
local_l2_addr.l2_family = PF_BLUETOOTH;
bacpy(&local_l2_addr.l2_bdaddr ,BDADDR_ANY);
iRel = bind(l2_sck, (struct sockaddr*)&local_l2_addr, sizeof(struct sockaddr_l2));
if(iRel & 0)
perror(&\nbind()&);
memset(&remote_l2_addr, 0 ,sizeof(struct sockaddr_l2));
remote_l2_addr.l2_family = PF_BLUETOOTH;
//printf(&\nConnect to %s\n&,argv[1]);
str2ba(argv[1],&remote_l2_addr.l2_bdaddr);
iRel = connect(l2_sck, (structsockaddr*)&remote_l2_addr, sizeof(struct sockaddr_l2));
if(iRel & 0)
perror(&\nconnect()&);
//get local bdaddr
len = sizeof(struct sockaddr_l2);
memset(&local_l2_addr, 0, sizeof(structsockaddr_l2));
//注意,getsockname()参数三是一个输入输出参数。输入时,为参数二的总体长度。输出时,
//为实际长度。
iRel = getsockname(l2_sck, (structsockaddr*) &local_l2_addr, &len);
if(iRel & 0)
perror(&\ngetsockname()&);
ba2str(&(local_l2_addr.l2_bdaddr), str);
//printf(&\nLocal Socketbdaddr:[%s]\n&, str);
printf(&l2ping: [%s] from [%s](datasize %d) ...\n&, argv[1], str, size);
for (i = 0; i & i++)
send_buf[L2CAP_CMD_HDR_SIZE + i] = 'A';
l2cap_cmd_hdr *send_cmd = (l2cap_cmd_hdr *)send_
l2cap_cmd_hdr *recv_cmd = (l2cap_cmd_hdr *)recv_
send_cmd-&ident =
//如上图所示,这一项为此CommandIdentifier
send_cmd-&len
= htobs(size);
send_cmd-&code = L2CAP_ECHO_REQ;
//如上图所示,此项为Command code.这项定为:
//Echo Request。对端会发送Response回来。code=L2CAP_ECHO_RSP
send_cmd-&ident =
if(send(l2_sck, send_buf, size +L2CAP_CMD_HDR_SIZE, 0) &= 0)
perror(&\nsend():&);
if(recv(l2_sck, recv_buf, size +L2CAP_CMD_HDR_SIZE, 0) &= 0)
perror(&\nrecv()&);
if (recv_cmd-&ident != id)
if( recv_cmd-&code ==L2CAP_ECHO_RSP)
//printf(&\nReceiveResponse Packet.\n&);
printf(&%d bytes from [%s]id %d\n&, recv_cmd-&len, argv[1], recv_cmd-&ident);
close(l2_sck);
所以说,如果想要发送接收signalingCommand。只需要建立l2cap RAWsocket. 并按规则填充command id,command code等。就可以接收发送了。
CommandCode: 这个值放在l2cap.h中。
#defineL2CAP_COMMAND_REJ 0x01
#defineL2CAP_CONN_REQ
#defineL2CAP_CONN_RSP
#defineL2CAP_CONF_REQ
#defineL2CAP_CONF_RSP
#defineL2CAP_DISCONN_REQ 0x06
#defineL2CAP_DISCONN_RSP 0x07
#defineL2CAP_ECHO_REQ
#defineL2CAP_ECHO_RSP
#defineL2CAP_INFO_REQ
#defineL2CAP_INFO_RSP
例二:任意PSM的L2CAP连接间数据的传输
server用来监听指定PSM的连接,并监听数据。同时,利用poll来查看peer是否断掉了。
#include&stdio.h&
#include&sys/types.h&
#include&sys/socket.h&
#include&stdlib.h&
#include&poll.h&
#include&bluetooth/bluetooth.h&
#include&bluetooth/hci.h&
#include&bluetooth/hci_lib.h&
#include&bluetooth/l2cap.h&
void *Read_thread(void* pSK);
intmain(int argc, char** argv)
int iRel = 0;
int sk = 0;
struct sockaddr_l2 local_
struct sockaddr_l2 remote_
int nsk = 0;
pthread_t nth = 0;
struct l2cap_
int optlen = 0;
int slen = 0;
char str[16] = {0};
if(argc & 2)
printf(&\nUsage:%s psm\n&,argv[0]);
// create l2cap socket
sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET,BTPROTO_L2CAP);
//发送数据,使用SOCK_SEQPACKET为好
if(sk & 0)
perror(&\nsocket():&);
local_addr.l2_family = PF_BLUETOOTH;
local_addr.l2_psm = htobs(atoi(argv[argc-1]));
//last psm
bacpy(&local_addr.l2_bdaddr,BDADDR_ANY);
iRel = bind(sk, (struct sockaddr*)&local_addr, sizeof(struct sockaddr));
if(iRel & 0)
perror(&\nbind()&);
//get opts
// in mtu 和 out mtu.每个包的最大值
memset(&opts, 0, sizeof(opts));
optlen = sizeof(opts);
getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS,&opts, &optlen);
printf(&\nomtu:[%d]. imtu:[%d].flush_to:[%d]. mode:[%d]\n&, opts.omtu, opts.imtu, opts.flush_to,opts.mode);
//set opts. default value
opts.omtu = 0;
opts.imtu = 672;
if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS,&opts, sizeof(opts)) & 0)
perror(&\nsetsockopt():&);
iRel = listen(sk, 10);
if(iRel & 0)
perror(&\nlisten()&);
len = sizeof(struct sockaddr_l2);
memset(&remote_addr, 0,sizeof(struct sockaddr_l2));
nsk = accept(sk, (structsockaddr*)(&remote_addr), &len);
if(nsk & 0)
perror(&\naccept():&);
ba2str(&(remote_addr.l2_bdaddr),str);
printf(&\npeerbdaddr:[%s].\n&, str);
//得到peer的信息
iRel = pthread_create(&nth, NULL,Read_thread, &nsk);
if(iRel != 0)
perror(&pthread_create():&);
pthread_detach(nth);
void *Read_thread(void* pSK)
//struct pollfd fds[10];
char buf[1024] = {0};
int iRel = 0;
int exit_val = 0;
//fds[0].fd = *(int*)pSK;
//fds[0].events = POLLIN | POLLHUP;
(int)(*(int*)pSK);
fds[0].events
if(poll(fds, 1, -1) & 0)
perror(&\npoll():&);
if(fds[0].revents & POLLHUP)
printf(&\n[%d] Hang up\n&,*(int*)pSK);
close(*(int*)pSK);
pthread_exit(&exit_val);
if(fds[0].revents & POLLIN)
memset(buf, 0 , 1024);
//read data
iRel = recv(*(int*)pSK, buf, 572,0);
//printf(&\nHandle[%d] Receive[%d] data:[%s]&, *(int*)pSK, iRel, buf);
#include&stdio.h&
#include&sys/types.h&
#include&sys/socket.h&
#include&unistd.h&
#include&bluetooth/bluetooth.h&
#include&bluetooth/hci.h&
#include&bluetooth/hci_lib.h&
#include&bluetooth/l2cap.h&
int main(intargc, char** argv)
int i = 0;
char buf[24] = &Sam is Good Guy!&;
struct sockaddr_l2 local_
struct sockaddr_l2 remote_
int iRel = 0;
if(argc & 3)
printf(&\nUsage:%s &bdaddr&&PSM&\n&, argv[0]);
sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET,BTPROTO_L2CAP);
if(sk & 0)
perror(&\nsocket():&);
//bind. bluetooth好像不许有无名Socket
local_addr.l2_family = PF_BLUETOOTH;
bacpy(&local_addr.l2_bdaddr,BDADDR_ANY);
iRel = bind(sk, (struct sockaddr *)&local_addr,sizeof(struct sockaddr));
if(iRel & 0)
perror(&\nbind()&);
memset(&remote_addr, 0, sizeof(structsockaddr_l2));
remote_addr.l2_family = PF_BLUETOOTH;
str2ba(argv[1], &remote_addr.l2_bdaddr);
remote_addr.l2_psm = htobs(atoi(argv[argc-1]));
connect(sk, (structsockaddr*)&remote_addr, sizeof(struct sockaddr_l2));
for(i = 0; i & 60; i++)
iRel = send(sk, buf, strlen(buf)+1, 0);
printf(&Send [%d] data\n&,strlen(buf)+1);
close(sk);
1. 在Linux 网络编程中,主动发起连接方,因为不关心地址具体是什么,所以可以作为无名socket,也就是说可以不bind. 但Bluetooth则不可以,一定需要bind.
2. poll可以查出连接断连,但需要注意:断开的revent值为:11001B。也就是说:POLLIN |POLLERR |POLLHUP。
3. 被连接一方,一定要指定PSM。
Servicediscovery机制提供client应用程序侦测server应用程序提供的服务的能力,并且能够得到服务的特性。服务的品质包含服务type或服务class.
SDP也提供SDP server与SDP client之间的通讯。SDP server维护着一个服务条目(service record)列表.每个服务条目描述一个单独的服务属性。 SDP client可以通过发送SDP request来得到服务条目。
如果一个client或者依附于client之上的应用程序决定使用某个service. 它创建一个单独的连接到service提供者。 SDP 只提供侦测Service的机制,但不提供如何利用这些Service的机制。这里其实是说:SDP只提供侦测Service的办法,但如何用,SDP不管。
每个Bluetooth Device最多只能拥有一个SDP Server。如果一个Bluetooth Device只担任Client,那它不需要SDP Server。但一个Bluetooth Device可以同时担当SDP Server和SDP client.
ServiceRecord(Service 条目):
一个service是一个实体为另一个实体提供信息,执行动作或控制资源。一个service可以由软件,硬件或软硬件结合提供。
所有的Service信息都包含于一个Service Record内。一个Service Record 包含一个Service attribute(Service属性) list.
在一个SDP Server内,每个Service Record拥有一个32-bit的唯一性数据。通常,这个唯一性只是在每个SDP Server内部。 如果SDP Server S1 和SDP Server S2拥有同样的一个Service Record。那他们在不同SDP Sever内的独特数值并不一定相同。
SDP在SDP Server增加或减少Service Record时,并不会通知SDP client.
ServiceAttribute(Service 属性):
每个Service属性描述servcie的特性.一个Service Attribute由2部分:
AttributeID + Attribute Value。
AttributeID:16-bit无符号整数,用于区别一个Service Record内的其它属性。
AttributeValue:Attribute值。
ServiceClass:
每个Service 都是某个Service Class的实例. Service Class定义了Service Record中包含的Service 属性。属性ID,属性值都被定义好了。
每个Service Class也有一个独特ID。这个Service Class标识符包含在属性值ServiceClassIDList属性中。并描绘为UUID。自从Service Record中的属性格式以及含义依赖于Service Class后,ServiceClassIDList属性变得非常重要。
SearchingFor Service:
ServiceSearch transaction(事务)允许client得到Service Record Handle。一旦SDP Client得到Service Record Handle,它就可以请求这个Record内具体属性的值。
如知道某个属性值UUID,则可以通过查找UUID查到这个属性。
UUID: universally uniqueidentifier.(唯一性标识符)
SDP协议栈使用request/response模式工作,每个传输过程包括一个request protocoldata unit(PDU)和一个response PDU. SDP使用L2CAP连接传输数据。在发送Request PDU但未收到Response PDU之前,不能向同一个server再发送Request PDU。
PDU ID:用来识别PDU。
TransactionID:用来识别Request PUD以及Response PUD。并用来对比某个Response PUD是否对应着Request PUD。
关于rfcomm
测试端输入字符串,并显示在服务端。
#include &stdio.h&
#include &stdlib.h&
#include &unistd.h&
#include&sys/socket.h&
#include&bluetooth/bluetooth.h&
#include&bluetooth/rfcomm.h&
int main( int argc , char**argv)
struct sockaddr_rc addr={0};
char *dest,* //=&00:11:67:32:61:62&;
if(argc==2)
dest=argv[1];
printf(&prarmerror/n&);
// allocate a socket
s=socket(PF_BLUETOOTH,SOCK_STREAM,BTPROTO_RFCOMM);
perror(&createsocket error&);
// set the connection parameters(who to connect to)
addr.rc_family=AF_BLUETOOTH;
addr.rc_channel=(uint8_t)1;
str2ba(dest,&addr.rc_bdaddr);
// connect to server
printf(&connectting.../n&);
status=connect(s,(struct sockaddr *)&addr,sizeof(addr));
// send a message
if(status==0)
printf(&scuess!/n&);
status=write(s,&hello!&,6);
scanf(&%s&,buf);
status=write(s,buf,strlen(buf));
if(status&0) perror(&uh oh&);
}while(strcmp(buf,&goodbye&)!=0);
printf(&Failed!/n&);
#include &stdio.h&
#include &stdlib.h&
#include &unistd.h&
#include&sys/socket.h&
#include&bluetooth/bluetooth.h&
#include&bluetooth/rfcomm.h&
int main (int argc,char**argv)
struct sockaddr_rc loc_addr ={0},rem_addr={0};
char buf[1024] ={0};//,*
int s,client, bytes_read,
int opt = sizeof(rem_addr);
printf(&Creating socket.../n&);
s =socket(PF_BLUETOOTH,SOCK_STREAM,BTPROTO_RFCOMM);
perror(&createsocket error&);
printf(&success!/n&);
loc_addr.rc_family=AF_BLUETOOTH;
loc_addr.rc_bdaddr=*BDADDR_ANY;
loc_addr.rc_channel=(uint8_t)1;
printf(&Binding socket.../n&);
result=bind(s,(struct sockaddr *)&loc_addr,sizeof(loc_addr));
if(result&0)
perror(&bind socket error:&);
printf(&success!/n&);
/*result=ba2str(&loc_addr.rc_bdaddr,addr);
if(result&0)
perror(&addrconvert error&);
printf(&localaddr is:%s/n&,addr);*/
printf(&Listen... &);
result=listen(s,1);
if(result&0)
printf(&error:%d/n:&,result);
perror(&listen error:&);
printf(&requested!/n&);
printf(&Accepting.../n&);
client= accept(s,(struct sockaddr *)&rem_addr,&opt);
if(client&0)
perror(&accepterror&);
printf(&OK!/n&);
ba2str(&rem_addr.rc_bdaddr,buf);
fprintf(stderr,&accepted connection from %s /n&,buf);
memset(buf,0,sizeof(buf));
bytes_read = read(client,buf,sizeof(buf));
if(bytes_read&0)
printf(&received[%s]/n&,buf);
if(strcmp(buf,&goodbye&)==0)
memset(buf,0,bytes_read);
close(client);
return 0 ;
本文已收录于以下专栏:
相关文章推荐
Bluez作为当前最成熟的开源蓝牙协议栈,在Linux的各大发行版中已经得到了广泛的应用。在桌面环境下,使用Bluez应该已经没有太大的问题,本文的主要目的是介绍在嵌入式平台上,搭建和配置Bluez的...
如果编译linux内核时,配置了CONFIG_BLUEZ,
则linux系统执行的第一个有关bluez的函数是bluez_init(net/socket.c)
调用路径main.c-&init-&...
人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..
在bluez启动过程中,各种插件的初始化尤为重要,没有这些插件,很多功能将无法实现。
2.3.5 plugin的初始化
插件的初始化,是什么的干活,其实还是很重要的,我们来看看吧。
众所周知,现在很多设备开始用上类蓝牙4.0技术
Bluedroid UIPC转发命令机制
关于蓝牙协议栈体系结构
底层硬件模块
1、利用2400M~2483.5M频带
2、采用调频方式传输数据,一共有79/EDR,40/BLE个hops,每秒
...
Linux下Bluez的编程实现
1、蓝牙的各个协议栈的简介........................................................................
主要摘取对于HCI、l2cap、sdp和rfcomm的一些应用编程。
一、HCI层协议概述
1、HCI Command Packets
详见bluez源码:lib...
他的最新文章
讲师: 许鹏
讲师:董付国
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)}

我要回帖

更多关于 bluez的库和头文件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信