基于Bluez的应用程序的开发 下载本文

memset(&addr, 0, sizeof(addr)); addr.l2_family = AF_BLUETOOTH; bacpy(addr.l2_bdaddr, src); addr.l2_psm = xxx;

if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror(\ goto error; }

注意:

struct sockaddr_l2 {

sa_family_t l2_family; //必须为 AF_BLUETOOTH

unsigned short l2_psm; //与前面PSM对应,这一项很重要 bdaddr_t l2_bdaddr; //Remote Device BDADDR unsigned short l2_cid; };

4. 发送数据到Remote Device: send()或write()都可以。 5. 接收数据: revc() 或read() 以下为实例:

注:在Bluetooth下,主动去连接的一端作为主机端。被动等别人连接的作为Client端。 背景知识1:Bluetooth设备的状态

之前HCI编程时,是用 ioctl(HCIGETDEVINFO)得到某个Device Info(hci_dev_info).其中flags当时解释的很简单。其实它存放着Bluetooth Device(例如:USB Bluetooth Dongle)的当前状态:

其中,UP,Down状态表示此Device是否启动起来。可以使用ioctl(HCIDEVUP)等修改这些状态。

另外:就是Inquiry Scan, PAGE Scan这些状态:Inquiry Scan状态表示设备可被inquiry. Page Scan状态表示设备可被连接。

参考:L2CAP编程,http://blog.csdn.net/baozhongchao/archive/2009/10/26/4728751.aspx

3.4、SDP协议简介

Service Discovery Protocol(SDP)提供一种能力,让应用程序有方法发现哪种服务可用以及这种服务的特性。服务发现协议(SDP或Bluetooth SDP)在蓝牙协议栈中对蓝牙环境中的应用程序有特殊的含意,发现哪个服务是可用的和确定这些可用服务的特征。SDP定义了bluetooth client发现可用bluetooth server服务和它们的特征的方法。这个协议定义了客户如何能够寻找基于特定属性的服务而不让客户知道可用服务的任何知识。SDP提供发现新服务的方法,在当客户登录到正在操作的蓝牙服务器的一个区域时是可用的时。

Service discovery机制提供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. Service Record(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.

Service Attribute(Service 属性):

每个Service属性描述servcie的特性.一个Service Attribute由2部分: Attribute ID + Attribute Value。

Attribute ID:16-bit无符号整数,用于区别一个Service Record内的其它属性。 Attribute Value:Attribute值。 Service Class:

每个Service 都是某个Service Class的实例. Service Class定义了Service Record中包含的Service 属性。属性ID,属性值都被定义好了。每个Service Class也有一个独特ID。这个Service Class标识符包含在属性值ServiceClassIDList属性中。并描绘为UUID。自从Service Record中的属性格式以及含义依赖于Service Class后,ServiceClassIDList属性变得非常重要。

Searching For Service:

Service Search transaction(事务?)允许client得到Service Record Handle。一旦SDP Client得到Service Record Handle,它就可以请求这个Record内具体属性的值。 如果某个属性值UUID,则可以通过查找UUID查到这个属性。 UUID: universally unique identifier.(唯一性标识符)

SDP协议栈使用request/response模式工作,每个传输过程包括一个request protocol data unit(PDU)和一个response PDU. SDP使用L2CAP连接传输数据。在发送Request PDU但未收到Response PDU之前,不能向同一个server再发送Request PDU。 PDU:protocol Data unit PDU ID:用来识别PDU。 TransactionID:

用来识别Request PUD以及Response PUD。并用来对比某个Response PUD是否对应着Request PUD。

4、Openobex

4.1、Openobex简介

Welcome to the Open OBEX project. The overall goal of this project is to make an open source implementation of the Object Exchange (OBEX) protocol. OBEX is a session protocol and can best be described as a binary HTTP protocol. OBEX is optimised for ad-hoc wireless links and can be used to exchange all kind of objects like files, pictures, calendar entries (vCal) and business cards (vCard).

OBEX was specified by the IrDA? (Infrared Data Association), and although the protocol is very good for Infrared connections, it is not limited to it. In fact OBEX does not specify the top or bottom API making it very flexible and can run over most transports like TCP/IP and Bluetooth. Therefore OBEX is also called IrOBEX when used over the Infrared medium. There are some transport modules for serial links (cable OBEX) too.

Today, OBEX is builtin in many devices e.g. PDA's like the Palm Pilot, and mobile phones like the Sony Ericsson R320, R520, T68, T610, T630, K700 and many later phones, Siemens S25, S35, S45, S55, S65 Nokia NM207 and Nokia 9110 Communicator. The HP Scanner? CapShare 920 can also talk OBEX in addition to JetSend. Microsoft Windows2000 has also builtin OBEX support. Link types currently supported by OpenOBEX are:

INFRARED DATA ASSOCIATION ? (IrDA) http://www.irda.org

USB-IF, Inc. http://www.usb.org

Bluetooth(TM) http://www.bluetooth.com

Support for TCP/IP links, file descriptors and custom transports is also provided.

OBEX全称为Object Exchange,中文对象交换,所以称之为对象交换协议。它在此软件当中有着核心地位,文件传输和IrMC同步都会使用到它。OBEX协议构建在IrDA架构的上层. OBEX协议通过简单的使用“PUT”和“GET”命令实现在不同的设备、不同的平

台之间方便、高效的交换信息。支持的设备广泛,例如PC,PDA,电话,摄像头,自动答录机,计算器,数据采集器,手表等等。OBEX协议定义了一种柔性的概念——objects。也即是对象。这些对象可以包括文件,诊断信息,电子商务卡片,银行的存款等等。Objects在这里没有高级的技术含义,而是视你的应用而定。OBEX协议小到可作“命令和控制”功能,例如对电视机,录像机等的操作。大道可以做很复杂的操作,例如数据库的事务处理和同步。

OBEX能够具有以下几个特点: 1、 友好的应用——可实现快速开发。 2、 紧缩——可用在资源有限的小型设备上。 3、 跨平台

4、 柔性的数据支持。

5、 方便的作为其他Internet传输协议的上层协议。

6、 可扩展性——提供了对未来需求的扩充支持而不影响以存在的实现。例如可扩展安全,

数据压缩等。 7、 可测试可调试。

4.2、Openobex与bluez编程实现

如下表:基于OBEX和BlueZ的数据传输的步骤 步骤 函数 OBEX_Init() 意义 用于初始化一个obex instance handle; arg1:OBEX_TRANS_BLUETOOTH用于声明传输协议为bluetooth; arg2:callback function; arg3:flag=OBEX_FL_KEEPSERVER,接收到请求后,服务器可以继续接收其他客户端的请求; 设置用户自己的变量,该函数的使用完全取决于用户自己; 一个专用于蓝牙协议的服务端函数,用于监听客户端发送的请求。该函数内部创建了一个 socket(调用socket(AF_BLUETOOTH,SOCK_STREAM,BTPROTO_RFCOMM)),bind该socket到本地蓝牙地址,将该socket转化为监听sockt,之后该socket才能够监听端口上来自客户端的连接请求; 1 2 OBEX_SetUserData() BtOBEX_ServerRegister() 3 OBEX_HandleInput() 4 函数用于读取并处理接收到的数据,如果没有数据到达,该函数将会阻塞;该函数内部调用了selet()函数,向系统登记了参数handle的客户端sockt与服务端sockt,让系 统监听socket上的事件,如果是服务端socket上有数据到达,则调用accept()函数为客户端创建一个新的sockt,如果OBEX_Init()的flag不是设置为OBEX_FL_KEEPSERVER,则关掉服务端socket,禁止其他客户端的连接请求; 该函数返回上述客户端的socket。 函数内部重新创建了一个obex instance handle,并将上述服务器handle的参数复制到该handle,获得服务器handle的fd(accept为客户端创建的socket)后,清除服务器本身的fd; 该函数同时也为新创建的obex instance handle设置callback function及Userdata;至此,已经为客户端创建了一个与服务端完全独立的obex instance handle,此后该服务端的操作都由该handle标识,而服务器的socket则继续监听其他客户端的连接请求。 OBEX_CMD_CONNECT 一个请求即将到来。 调用OBEX_ObjectSetRsp(object,OBEX_RSP_CONTINUE,OBEX_RSP_SUCCESS)设置响应操作码 第一个接收到的请求包已经被解析 收到n个此事件,说明客户端正在传输文件内容 OBEX_CMD_PUT OBEX_ObjectSetRsp(object,OBEX_RSP_CONTINUE,OBEX_RSP_SUCCESS)设置响应操作码;此时,客户端文件传输完毕,需进行处理: OBEX_ObjectGetNextHeader()分别取得文件的名称与内容; OBEX_CMD_PUT 一个请求即将到来 OBEX_CMD_DISCONNECT OBEX_ObjectSetRsp(object,OBEX_RSP_SUCCESS,5 CALLBACK : (OBEX_EV_ACCEPTHINT) OBEX_ServerAccept() 6 7 CALLBACK : OBEX_EV_REQDONE CALLBACK : OBEX_EV_REQHINT 8 9 10 CALLBACK : OBEX_EV_REQCHECK CALLBACK : OBEX_EV_PROGRESS CALLBACK : OBEX_EV_REQ 11 12 13 14 CALLBACK : OBEX_EV_REQDONE CALLBACK : OBEX_EV_REQHINT CALLBACK : OBEX_EV_REQ