现在的位置: 首页 > 综合 > 正文

蓝芽:Linux与手机

2013年04月01日 ⁄ 综合 ⁄ 共 10733字 ⁄ 字号 评论关闭

当蓝芽SIG成立的时候,其发起者曾经指出,当蓝芽能够被集成入单芯片之中、成本下降到5美元的时候,将得到极大地普及。而今,小小的一个五号电池大小的几十块人民币的东东就可以提供这个功能了,蓝芽也真的进入了我的生活。
利用蓝芽在手机之间传送图片不是什么新鲜事,我们现在做的是要连接Linux主机和蓝芽手机。
如果你喜欢这篇文章,别忘了谢谢偷走我前一个手机的兄弟,否则我也没有这么快用上蓝芽手机。

手机与计算机的通信与文件传输。
来点基础

蓝芽最早由瑞典Ericsson提出,其名称是古代瑞典的一位国王,因为总吃某种诡异果品 (似乎是草莓的一个品种,不太了解植物学,错了的话不要拍我),把牙齿弄得蓝乎乎的,被称作蓝牙(bluetooth)。古代瑞典可不像现在的一样,那时的瑞典统治整个北欧,可气派了,同样有野心的爱立信于是使用BT这个名字来命名这个被他们寄予厚望的短距离互联技术。

Bluetooth用于连接个人周边的外围设备,比如无线耳机、打印机、扫描仪、手机、计算机等等,在这些设备之间交换文件和数据,替代低速串行线的工作,常用用途包括

    * 文件共享、传输
    * 语音传输
    * 远程打印
    * RS-232串行口线替代

因为Bluetooth的功能十分实用、一经提出,立刻有一种一呼百应的感觉,随着成本的下降,蓝芽的用途也越来越广(当然了,这个过程也不是一帆风顺的了),大量的中低端手机也开始装备上了这项技术,以其更丰富、完善的协议栈,略高的传输速率,以及相对于红外线来说摆脱了必须毫无障碍的束缚,几乎完全取代了原来商务手机上普遍装备的红外接口。

蓝芽来到中国,把“牙”替换成了更有东方美感的“芽”字。

蓝芽实际上并不是一种简单的协议,相反,十分复杂

    * 从网络结构和组网方式讲,蓝芽在10米区域内形成一个网络,其中可以有1个主设备,7个从设备,一共8个激活的设备,当然睡觉的设备还可以有很多,不打呼噜就行了。对于更多的设备,可以使用ad hoc的方式互联,学网络的同学们看到这个来精神了吧,不过我可不打算讲了。
    * 从应用来看,BT支持语音通信和串行线模拟,并且通过Profile来支持各种周边智能设备的应用,比如耳机、打印机……并且定义了一套服务发现和调用机制,还是瞒有意思的。

蓝芽最有意思的模过于第2层互联和应用层的Profile了,至于底层的跳频什么的倒是新意不大。另外就是,虽然蓝芽使用的频率和微波炉烹饪的频率毫无二致,但发射功率还是很小的,基本不足以把我们这么大块的肉弄熟。
Linux下的蓝芽协议栈

Linux 下有若干个蓝芽协议栈,目前生存状况比较健康的是bluez和affix,后者大概是Nokia支持的吧,前者则是目前蓝芽的Linux官方版本,集成在 Linux内核之中,也就是说,如果你有一个比较新的2.6内核,那么,你多半已经支持蓝芽了,而如果还不支持的话,重新编译一下也就好了。

不要觉得Linux的协议栈比不上Windows里面的,事实是,这里风景独好,bluez协议栈支持的硬件设备远远多于windows系统支持的。如果你和我一样只用Linux,那么,买了蓝芽适配器之后,大概就可以把臃肿的驱动光盘丢进垃圾桶,然后心情愉快的使用蓝芽了,跟我来吧,

内核的协议栈支持主要包含这么几个部分:

    * HCI. 这个是最底层的了,称为 Host Control Interface. 之所以称为 HCI 是源于蓝芽的应用模型的。蓝芽是连接智能外设的无线接口,接口的一侧是设备,另一侧就是主机 (Host) 了,采用类似记法的还有 USB, IEEE1394,所以,从设计初衷来看,这几个东东都是针对差不多的市场的,当然,各有所长了。一个蓝芽适配器是否能被驱动起来,就看 HCI 的支持性了。最常见的蓝芽适配器就是笔者持有的这类 USB 接口的了,对于大部分标准的蓝芽设备,它的驱动模块是: hci-usb,对于我们的
2.6 内核,插入这个适配器,该模块就被自动加载了。
    * 在 HCI 之上是 L2CAP,Logical Link Control and Adaptation Protocal 这一层的功能承上启下,向上层提供异步数据传输的链路控制功能,所谓异步,就是不存在一个主时钟来同步所有传输的一种传输方式,通常用于数据的传输;与之相反,同步传输是完全与时钟同步的,通常用在诸如语音或是多媒体通话之中,在蓝芽中,语音同步传输也是被支持的,bluez 协议栈中的 SCO 就是支持同步模式的。
    * L2CAP之上有两个协议被较广地使用着:RFCOMM和BNEP,前者用于取代传统的串行口,包括串行口上的各种应用,比如,传真和拨号上网、打印机、文件图片等数据传输;后者则可以提供一个以太网接口,更适于计算机组网。自然地,对于手机和计算机之间,RFCOMM 总是更常被用到。

截止到这里就是内核提供的几乎所有蓝芽协议栈了,不过,仅有这些,蓝芽还不足以为我所用,只有有了用户态的协议栈和工具相配合,才有幸福的蓝芽生活 :)
用户空间中的蓝芽协议栈与相关工具

接着刚才的协议栈,这次势在用户空间实现的了:

    * 在最上层,蓝芽定义了很多的Profile,每个Profile对应着一种应用,比如打印、耳机(Headset)、文件传输、Fax/Modem拨号功能等。其中,文件交换对应着Obex协议,这是一个基于蓝芽、红外(IrDA)、串口等介质的文件(对象)交换协议,这几种介质被列到一起一点也不会让人感到意外,毕竟前两个都是用来在某种意义上取代串口的。当然,有些Profile,比如一些人机交互设备 (键盘鼠标之类的) 的profile 是在内核中实现的。
    * 实际上,我们还有一个重要的协议没有介绍,这就是SDP --- 服务发现协议,这个协议可以认为和RFCOMM处于统一层次,因为它并不承载于RFCOMM之上,不过,这个协议却十分特殊而重要,通过它,我们才能识别出某一蓝芽设备提供了哪些服务(Profile),从而为我所用。

嗯,协议栈已经有了,那我们怎么使用蓝芽呢? 回忆一下怎么把大象放到冰箱里吧:

    * 打开冰箱门
    * 把大象放进冰箱
    * 关上冰箱门

就是这么简单,一个蓝芽服务也是这么容易:

    * 找到蓝芽设备,这是HCI层负责的,使用 bluez-utils 包提供的 hcitool 来找到蓝芽设备;
    * 找到服务,RFCOMM 是通过不同的频道 (channel) 来提供不同的Profile的,所以,我们需要找到我们要用的服务在设备上的哪个频道上,这是通过同一个软件包里的 sdptool 来完成的,没错,就是 SDP,服务发现协议。
    * 连接恰当的服务,使用

蓝芽的特点就是如上所属的那些了,而用户态的工具所要完成的任务就是:

    * 发现服务
    * 使用服务

启动 HCI 设备

首先,我们需要启动 hcid,让 HCI  层的通信可以进行,对于 Debian 用户来说,你需要安装 bluez-utils 包,并启动 hcid。如果你运行了 bluetooth 服务,并在 /etc/default/bluetooth 之中设置启动了 HCID 的话

    HIDD_ENABLED=1

插入 USB 适配器后,你的 hcid 就已经在运行了,看看相关信息吧:

inspiration:/etc/bluetooth# hciconfig -a
hci0:   Type: USB
        BD Address: 11:11:11:11:11:11 ACL MTU: 678:8 SCO MTU: 48:10
        UP RUNNING PSCAN ISCAN
        RX bytes:413 acl:0 sco:0 events:19 errors:0
        TX bytes:323 acl:0 sco:0 commands:19 errors:0
        Features: 0xbf 0xfe 0x8d 0x78 0x08 0x18 0x00 0x00
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
        Link policy: RSWITCH HOLD SNIFF PARK
        Link mode: MASTER
        Name: 'inspiration-0'
        Class: 0x3e0100
        Service Classes: Networking, Rendering, Capturing, Object Transfer, Audio
        Device Class: Computer, Uncategorized
        HCI Ver: 1.2 (0x2) HCI Rev: 0x1fe LMP Ver: 1.2 (0x2) LMP Subver: 0x1fe
        Manufacturer: Integrated System Solution Corp. (57)
这个过程是自动的,当然,你也可以用 hciconfig (8) 来手工控制。
寻找蓝芽设备

HCI 已经启动了,现在就可以用它来寻找蓝芽设备了,当然,一定要先开启蓝芽设备的蓝芽功能,这个不是废话,手机的蓝芽是默认关闭的,只有在手动控制之下才会发送信号,允许被扫描到,不过设备的个体差异性太大了,这里就没法介绍了,我假设你已经自己摸索或参照说明书打开了设备的蓝芽电源,现在,找找看吧

inspiration:/home/gnawux# hcitool scan
Scanning ...
        00:17:00:7B:18:B8       Motorola SLVR

命令一出,略等片刻,蓝芽设备就会被顺利地找到。
查看设备提供的服务

利用 SDP 协议,我们还可以查看每个设备都有功能,能提供什么服务,每种基于 RFCOMM 的服务都使用某种协议,占据一个“频道 (channel)”,这是我们使用服务时的一个重要参数

下面是例子,先看看自己:

gnawux@inspiration:~$ sdptool browse local
Browsing FF:FF:FF:00:00:00 ...
Service Name: OBEX Object Push
Service RecHandle: 0x10000
Service Class ID List:
  "OBEX Object Push" (0x1105)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 9
  "OBEX" (0x0008)
Profile Descriptor List:
  "OBEX Object Push" (0x1105)
    Version: 0x0100

再看看别人 (手机)
gnawux@inspiration:~$ sdptool browse 00:17:00:7B:18:B8
Browsing 00:17:00:7B:18:B8 ...
Service RecHandle: 0x0
Service Class ID List:
  "SDP Server" (0x1000)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "SDP" (0x0001)
Profile Descriptor List:
  "SDP Server" (0x1000)
    Version: 0x0100
Service Name: Dialup Networking Gateway
Service Description: Dialup Networking Gateway
Service Provider: Motorola
Service RecHandle: 0x10001
Service Class ID List:
  "Dialup Networking" (0x1103)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 1
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
  code_ISO639: 0x7a68
  encoding:    0x6a
  base_offset: 0xc800
Profile Descriptor List:
  "Dialup Networking" (0x1103)
    Version: 0x0100
Service Name: Voice Gateway
Service Description: Headset Audio Gateway
Service Provider: Motorola
Service RecHandle: 0x10003
Service Class ID List:
  "Headset Audio Gateway" (0x1112)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 3
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
  code_ISO639: 0x7a68
  encoding:    0x6a
  base_offset: 0xc800
Profile Descriptor List:
  "Headset" (0x1108)
    Version: 0x0100
Service Name: Handsfree Voice Gateway
Service Description: Handsfree Voice Gateway
Service Provider: Motorola
Service RecHandle: 0x10007
Service Class ID List:
  "Handfree Audio Gateway" (0x111f)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 7
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
  code_ISO639: 0x7a68
  encoding:    0x6a
  base_offset: 0xc800
Profile Descriptor List:
  "Handsfree" (0x111e)
    Version: 0x0101
Service Name: OBEX Object Push
Service Description: OBEX Object Push
Service Provider: Motorola
Service RecHandle: 0x10008
Service Class ID List:
  "OBEX Object Push" (0x1105)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 8
  "OBEX" (0x0008)
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
  code_ISO639: 0x7a68
  encoding:    0x6a
  base_offset: 0xc800
Profile Descriptor List:
  "OBEX Object Push" (0x1105)
    Version: 0x0100
Service Name: OBEX File Transfer
Service Description: OBEX File Transfer
Service Provider: Motorola
Service RecHandle: 0x10009
Service Class ID List:
  "OBEX File Transfer" (0x1106)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 9
  "OBEX" (0x0008)
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
  code_ISO639: 0x7a68
  encoding:    0x6a
  base_offset: 0xc800
Profile Descriptor List:
  "OBEX File Transfer" (0x1106)
    Version: 0x0100
Service Name: Image Push
Service Description: Image Push
Service Provider: Motorola
Service RecHandle: 0x1000a
Service Class ID List:
  "Imaging Responder" (0x111b)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 10
  "OBEX" (0x0008)
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
  code_ISO639: 0x7a68
  encoding:    0x6a
  base_offset: 0xc800
Profile Descriptor List:
  "Imaging" (0x111a)
    Version: 0x0100

手机的比较多,我也没有截短,方便大家看看手机可能提供的丰富蓝芽功能。下一节我们将介绍几个利用蓝芽可以做的事情:
蓝芽应用
上一节,通过 sdptool,我们看到笔者的手机提供了拨号、耳机、文件传输等功能,现在我们就来试试看。
利用蓝芽传输文件

利用蓝芽传送文件使用的都是前面提到的 Obex 协议,这里介绍几个用法。
与手机互相推送文件

这是使用手机或计算机提供的"OBEX Object Push" (0x1105)服务,由另一方向其推送文件。使用的工具是 openobex-apps 包里的 obex_test工具

首先是向手机推送,对于我的手机,推送服务在频道8:

gnawux@inspiration:~$ obex_test -b  00:17:00:7B:18:B8 8
Using Bluetooth RFCOMM transport
OBEX Interactive test client/server.
> c
Connect OK!
Version: 0x10. Flags: 0x00
> p wangxu.jpg me.jpg
PUT file (local, remote)> name=wangxu.jpg, size=34177
Going to send 34177 bytes
Made some progress...
Made some progress...
Made some progress...
Made some progress...
Made some progress...
PUT successful!
> q
可以看到,执行完 obex_test 之后,进入一个交互状态,首先建立连接,然后传送文件 (本地文件名是 wangxu.jpg,存在手机上叫 me.jpg,这个是我随便取的),最后,退出。这个过程需要看着点手机屏幕,可能要你确认是否连接,文件存放在哪里,当然,这个和手机有关。

现在也可以看看手机向计算机推送,首先应该让手机进入接收状态,如果本地没有启动 Object PUSH 服务,己把它加上:

gnawux@inspiration:~$ sdptool add OPUSH
OBEX Object Push service registered
现在进入接收状态,注意要使用计算机 (local) 的地址和频道号:

gnawux@inspiration:~$ obex_test -b FF:FF:FF:00:00:00 9
Using Bluetooth RFCOMM transport
OBEX Interactive test client/server.
> s
现在,计算机进入了接收模式,在手机侧发送文件到计算机就可以了。
使用 obexftp 上传下载

使用"OBEX File Transfer" (0x1106)服务的 obexftp 是一个方便的工具,我们可以查看手机上的内容,并进行上传下载,对于我的手机,对应的频道是 9 (参考上面的 sdptool browse 的结果)。

看看有哪些目录:

gnawux@inspiration:~$ obexftp -b 00:17:00:7B:18:B8 -B 9 -l
Browsing 00:17:00:7B:18:B8 ...
Channel: 9
Connecting...done
Receiving "(null)"...|<?xml version="1.0" ?>
<!DOCTYPE folder-listing SYSTEM "obex-folder-listing.dtd">
<folder-listing>
<parent-folder />
<folder name="audio" size="0" type="folder" modified="20060805T144844Z" user-perm="RW" />
<folder name="video" size="0" type="folder" modified="20060805T144844Z" user-perm="RW" />
<folder name="picture" size="0" type="folder" modified="20060805T144844Z" user-perm="RW" />
<folder name="MMC(Removable)" size="0" type="folder" modified="19700101T000000Z" user-perm="RW" />
</folder-listing>
done
Disconnecting...done
可以看到,有四个有读写 (RW) 权限的目录,现在,再看看 audio 里面有什么

gnawux@inspiration:~$ obexftp -b 00:17:00:7B:18:B8 -B 9 -l audio
Browsing 00:17:00:7B:18:B8 ...
Channel: 9
Connecting...done
Receiving "audio"...|<?xml version="1.0" ?>
<!DOCTYPE folder-listing SYSTEM "obex-folder-listing.dtd">
<folder-listing>
<parent-folder />
<file name="a.mp3" size="977920" type="audio/mp3" modified="20060805T145050Z" user-perm="RW" />
</folder-listing>
done
Disconnecting...done
可以看到,这里有一个 mp3 文件,我们把它取下来

gnawux@inspiration:~$ obexftp -b 00:17:00:7B:18:B8 -B 9 -c audio -g a.mp3
Browsing 00:17:00:7B:18:B8 ...
Channel: 9
Connecting...done
Sending "audio"...done
Receiving "a.mp3"...-done
Disconnecting...done

经过一段漫长的等待,传送终于完成了,有点后悔选择这么大的文件进行传输。现在,再把 wangxu.jpg 放到 picture 目录去

gnawux@inspiration:~$ obexftp -b 00:17:00:7B:18:B8 -B 9 -c picture -p wangxu.jpg
Browsing 00:17:00:7B:18:B8 ...
Channel: 9
Connecting...done
Sending "picture"... done
Sending "wangxu.jpg"...\done
Disconnecting...done
其他 obexftp(1) 的用法,大家自己学习文档吧 :)
其他obex工具

还有 obexserver, qobex (qt based) 等工具,使用起来更为简单,就不介绍了。

利用蓝芽手机拨号

我们说过,蓝芽的一个几本功能就是模仿串口,串口的重要作用之一 (可能是最重要的了) 就是拨号,传统的 DTE 也就是 Modem 嘛。实际上,通过 rfcomm,蓝芽连接可以反映在 /dev/rfcomm0 这样的字符设备上,像串口一样操作。当然,我们最好先定义 /etc/bluetooth/rfcomm.conf,里面根据手机的设备号和频道号写上

rfcomm0 {
       # Automatically bind the device at startup
    bind yes;

       # Bluetooth address of the device
    device 00:17:00:7B:18:B8;

       # RFCOMM channel for the connection
    channel 1;

       # Description of the connection
    comment "Motorola SLVR L7";
}
这样,在启动 bluetooth 服务的时候,就已经自动连接上了,而不需要使用rfcomm (1) 命令自己费力气了。现在,可以使用任意一个喜欢的串口程序 (minicom, gtkterm 等等) 来对 /dev/rfcomm0 进行拨号了

输入 AT 命令的第一个命令:

AT

OK

试着播一下号

ATD139012345;

这个是随便写的号码,大家找认识的号码播哦 (故意少写了两位,省得万一试到人家头上,呵呵)。

拨号就是这么简单,理论上讲,GPRS 连接应该也可以实现,不过,没有笔者开通业务,就算了,留给读者自己研究吧,呵呵。
小结

  至此,Linux与蓝芽手机的全部内容,理论到操作已经全部完成了,基于的操作系统是使用 2.6 内核的 Debian GNU Linux,测试的手机包括 Motorola SLVR L7 和 Nokia N-Gage QD 各一部,蓝芽适配器芯片是 Integrated System Solution Corp. KY-BT100 Bluetooth Adapter,所有测试都非常顺利,也祝读者朋友玩得开心

抱歉!评论已关闭.