当前位置: 首页 > 编程日记 > 正文

Android上成功实现了蓝牙的一些Profile

前段时间做蓝牙方面的开发,Google的Android只实现了Handset/Handfree和A2DP/AVRCP等Profile,而其 它常用的Profile如HID/DUN/SPP/OPP/FTP/PAN等却没有实现,并且Google方面关于何时实现也没有一个时间表。

前段时间我实现了HID/DUN/SPP三个Profile,下一步实现OPP/FTP等Profile。具体的开发其实也简单,我是参照A2DP的代码进行的相关Profile的实现。

Android的Handset/Handfree的实现方式和A2DP/AVRCP的方式有很大的不同,Handset/Handfree是直接 在bluez的RFCOMM Socket上开发的,没有利用bluez的audio plugin,而A2DP/AVRCP是在bluez的audio plugin基础上开发的,所以大大降低了实现的难度。其实bluez的audio plugin上也有Handset/Handfree的实现,但不知道为什么Google没有用它,而要在RFCOMM Socket上自己实现一个,这使得Handset/Handfree的实现显得比较复杂。

HID要用到bluez的input plugin,Android已经把它编译进去了,在system/lib/bluez-plugin/input.so下,与input.so一起的还 有audio.so库,那是供A2DP/AVRCP用的。参照frameworks/base/core/jni /android_server_BluetoothA2dpService.cpp,自己写一个HID用的的.cpp文件,其中跟A2DP一样利用 DBUS调用input.so库的CreateDevice/Connect/Disconnect等函数,具体源码在external/bluez /utils/input/manager.c和external/bluez/utils/input/device.c中。完了之后,参照 frameworks/base/core/java/android/server/BluetoothA2dpService.java和 frameworks/base/core/java/android/bluetooth/BluetoothA2dp.java及 frameworks/base/core/java/android/bluetooth/IBluetoothA2dp.aidl,自己分别写两个 JAVA类及AIDL接口,余下的就是在packages/apps/Settings/src/com/android/settings /bluetooth目录下的各个文件的修改了,比较省事的方法是搜一下A2DP,只要是A2DP要修改的地方照葫芦画瓢添加修改就是了。

DUN/SPP要用到bluez的serial plugin,因Android没有编译进去,所以要在external/bluez/utils/serial目录下写一个Android.mk,把它 编译进去,生成system/lib/bluez-plugin/serial.so库,其它的跟HID类似。

分类: Android, bluetooth 标签: bluetooth

Bluetooth FAQ on Android

2010年3月31日 zooyoo 没有评论

URL: http://sites.google.com/a/android.com/opensource/projects/bluetooth-faq

This FAQ refers to the Android Open Source codebase, and is written for platform developers with root access on devices such as the Androd Developer Phone.

Q. How do I compile Android with Bluetooth support enabled?
A. Add this to your BoardConfig.mk:
BOARD_HAVE_BLUETOOTH := true

Q. Does the emulator support Bluetooth?
A. Sorry, not at this time. This would make a nice project if someone wants to take this on.

Q. Bluetooth doesn’t work on my device. How should I debug Bluetooth?
A. First step – read the logs (adb logcat)! In particular look for ERROR or WARNING level messages regarding Bluetooth.
Andoird uses Bluez, which comes with some very useful debugging tools. Here are some examples, in the rough order I use to debug BT.
hciconfig -a # print BT chipset address and features. Useful to check if you can communicate with your BT chipset.
hcidump -XVt # print live HCI UART traffic.
hcitool scan # scan for local devices. Useful to check if RX/TX works.
l2ping ADDRESS # ping another BT device. Useful to check if RX/TX works.
sdptool records ADDRESS # request the SDP records of another BT device.

Q. Where are the logs for the Bluetooth deamons hcid and hciattach?
A. Like all Android system daemons, the STDOUT and STDERR are sent to /dev/null by default. If you want to view these logs you can run the daemons under logwrapper which redirects there output to logcat. Edit init.rc and init.PLATFORM.rc to run these daemons under logwrapper.

Q. I compiled my own system.img for the Android Developer Phone, and hciconfig -a works, but hcitool scan does not. Whats going on?
A. You probably need to install the firmware for the Bluetooth chipset. Unfortunately this firmware is not yet in the open source codebase. However you can adb pull and then adb push it from a stock T-Mobile G1. The location is.
/etc/firmware/brf6300.bin

Q. What Bluetooth Core version does Android support?
A. Bluetooth 2.0 + EDR.

Q. What is the architecture of Bluetooth in Android?
A. We are based on Bluez version 3.36. The diagram below shows our 1.0 layout:

Q. When will Java Bluetooth API’s be released in an SDK?
A. We are not ready to announce a release target for Bluetooth API’s. We do understand there is demand for a Bluetooth API, and it is a top priority for the Android Bluetooth team.

Q. What is needed for Bluetooth 2.1 and Simple Pairing support?
A. We need to move to a Bluez 4.x version.

Profile Support

Q. What is the status of Headset and Handsfree?
A. Android 1.0 is qualified for both HFP and HSP (in the AG role) profiles. We are gladly taking bug fixes on any remaining issues. The one significant feature we lack is eSCO support.

Q. What is the status of A2DP and AVRCP?
A. A2DP and AVRCP work is ongoing for the ‘cupcake’ release. We are using the Bluez audio plugin and Bluez SBC codec, with a custom audio path designed for the Android Audio sub-system. Qualificiation is not yet complete.

Q. What is the status of HID?
A. Some very early work is in cupcake – Bluez has an HID plugin which we compile:
external/bluez/utils/input/Android.mk
You can interact directly with this plugin using dbus-send and dbus-monitor. With a little study of the Bluez HID plugin API and some luck and you should be able to connect and use a HID keyboard or mouse. A lot of work remains to be done before we could officially claim HID is supported by the platform. For example we need to plumb the plugin API up in the Android Java framework. And the Android framework needs better support for HID input methods – new keymaps and mouse support. We do not yet have a release targetted for official HID support.

Q. What is the status for tethering – DUN and PAN.
A. Similar to HID, some very early work is in cupcake. Bluez has DUN and PAN daemons which we compile.
external/bluez/utils/dun/Android.mk
external/bluez/utils/pan/Android.mk
BNEP support is compiled into the kernel with cupcake. With a little experimentation running these daemons (dund or pand) and using pppd or iptables you can test tethering support. A lot of integration work remains before we could officially claim that DUN or PAN is supported by the platform. Like HID, we would need to plumb the DBUS API’s to these daemons up into the Android Java framework, and add code to setup the network paths via pppd and/or iptables. We do not yet have a release targetted for official DUN or PAN support.

分类: Android, bluetooth 标签: bluetooth

android1.0蓝牙问题浅谈1

2010年3月31日 zooyoo 没有评论

cupcake和donut中bluez用的是3.35, eclair中用的是4.47

以下转自:http://blog.sina.com.cn/s/blog_5dd76ed10100bqav.html

前段时间,研究android蓝牙,有些困惑,在android开发者论坛发帖请教,结果没人回复,无奈只好自己研究了一番。自问自答,希望对有相同困惑的朋友有所帮助,共同提高了,呵呵!android1.0蓝牙问题浅谈1

1/ android1.0平台嵌入的BlueZ stack是否支持A2DP? 根据代码分析,其实用的bluez是3.35版本。

BlueZ stack是开源社区提供的一套协议栈,其本身的功能是相当丰富的。其主要分为两部分:内核部分嵌在linux内核中,从linux2.4.6版本之后就 已经内嵌了bluez,之前的版本需要自己打补丁。内核部分主要在两个文件夹下driver和net。还有一部分是用户部分,主要包括lib和 utills工具集,从代码中就可以看到A2DP/AVRCP/HSP等profile都是支持的。当然了,bluez虽然强大,但是并不支持obex协 议及之上的FTP/OPP/BIP/SP等profile, 我想这主要是考虑到OBEX的广泛性,OBEX不仅是蓝牙文件传输的基础协议,也是IrDA的 基础。所以,OBEX也有一个专门的开源协议栈,即OpenOBEX,如果需要支持FTP等profile,只需要将OpenOBEX及之上的 OpenFTp等移植近来即可。

2/Android1.0对bluez stack做了什么工作?如果bluez已经支持了A2DP,那么google为什么不支持?
众所周知,Android平台是用JAVA写的,那么在App FRAME和linux用户空间之间需要JNI来实现两部分之间的通信。BLUEZ内核部分在linux内核中,用户部分(utils)在linux用户 空间。android做的工作就是首先用C++对bluez封装了一层FRAME,实现为COM接口的形式。然后在JNI之上,APP FRAME层用JAVA封装了一层接口,用来调用COM接口。然后上层应用APPLICATION是用FRAME中的JAVA类接口。由于android 只是封装了HSP/HFP,所以他并不支持A2DP/AVRCP等profile。

3/如果需要在android1.0平台上支持a2dp等协议,我该怎么办?都有什么解决方案

A2DP解决方案如下:
1)自己封装两层接口,模仿HSP的做法
2)跟踪google的蓝牙策略。
分析:
由于google已经将A2DP的支持提上了日程,并声称在09年第一季度就会支持A2DP/AVRCP,所以如果我从现在开始自己封装,鉴于人力/技术 等因素,很可能我还没做完,google就已经支持了,而且我做完之后的代码也不能作为开源代码提供给android,所以工作白做。得不偿失。
而且,由于bluez开源组织声称在即将推出的bluez4.x版本之后会对协议栈架构进行较大调整,产生后向兼容性问题。而google考虑到 android平台作为一个开源平台,其api稳定性是必须考虑的问题,所以其必然会采用4x版本(这也是google在android1.0 remove 蓝牙API的原因之一)。这样,自己开发的意义更是不复存在。

FTP/OPP解决方案:
1)移植OpenOBEX及之上的OpenFTP等。

分析:
由于google似乎并没有公布其支持FTP的schedule,所以如果要支持文件传输这一蓝牙最常用功能的话,我想只有自己想办法了。~~

分类: Android, bluetooth 标签: bluetooth

ARM平台上蓝牙协议栈Bluez的移植使用和配置(转)

2010年3月30日 zooyoo 没有评论

作者:刘旭晖 Raymond转载请注明出处

Email:colorant@163.com

BLOG:http://blog.csdn.net/colorant/

主页:http://rgbbones.googlepages.com/

Bluez作为当前最成熟的开源蓝牙协议栈,在Linux的各大发行版中已经得到了广泛的应用。在桌面环境下,使用Bluez应该已经没有太大的问 题,本文的主要目的是介绍在嵌入式平台上,搭建和配置Bluez的各个Profile运行所需做的工作,讨论可能遇到的问题,介绍一些工具的使用和工作原 理。因为本人的能力和测试时间有限,可能下文中有些理解、分析不一定准确,欢迎联系指正。

1         相关说明

1.1        网站资源

Bluez的官方网址:http://www.bluez.org/ 这里提供最新的源码下载,最近服务器崩溃了一次,有些东西没了。。。。

Bluez的Wiki:http://wiki.bluez.org/wiki/ 这里提供Bluez相关的Howto等文档资源

相关邮件列表:

https://lists.sourceforge.net/lists/listinfo/bluez-users 关于如何使用和配置Bluez,多数是在讨论PC环境下的问题。。。。

https://lists.sourceforge.net/lists/listinfo/bluez-devel Bluez开发者活动的地方,有什么Bug之类的怀疑,还有编程接口之类的问题,就发到这里吧。

1.2        工作环境

个人感觉,使用Bluez最大的问题就是文档的欠缺,除了Wiki上的有限资料以外,很难找到其它有用的文档。

由于Bluez的代码实现更新变化得很快,网上的许多文档介绍的都是早期版本的使用,再有的文章多数是基于成熟的Linux发行版,来讨论蓝牙设备的配置和使用,对于嵌入系统开发,自己编译,搭建和配置相关环境的文章很少。此外和具体蓝牙芯片相关的资料也很难找到。

这里我不打算也没有能力写一个完整的指南,只能基于前段时间在自己的板子上所做的工作,总结一下相关的步骤和所遇到的各类问题以及这期间所掌握的各种相关知识。希望能给有类似开发需求的朋友一些有益的帮助,下面是这篇文章所基于的工作环境:

?       硬件平台:基于ARM的嵌入式板子

?       蓝牙芯片:CSR BC4 ROM 版本芯片,不带eeprom

?       软件环境:Linux 2.6.21 ,自制文件系统

?       Bluez版本:bluez-libs 3.22  bluez-utils 3.22

2         编译

2.1        内核

相信多数人使用的都是2.6的内核了,在2.6的内核中要支持Bluez,只要你的内核版本不是太旧,无需打Patch,直接配置好就OK了,内核 里面的代码相对比较稳定了。当然,Bluez对一些Bluetooth协议栈新特性的支持,还是需要更新kernel代码的。你应该确认你使用的 kernel版本是否以及包含了对应的支持。

内核的配置,基本上把 networking下 — Bluetooth subsystem support 里的以下几项全部选上即可:

L2CAP protocol support

SCO links support

RFCOMM protocol support

RFCOMM TTY support

BNEP protocol support

HIDP protocol support

此外,在Bluetooth device drivers里选上你所需要支持的Bluetooth设备。我使用的CSR的chip是我们直接build在板子上,通过串口和cpu通讯的,芯片默认使用BCSP作为通讯协议,所以我选择了:

HCI UART driver

BCSP protocol support

如果你是通过usb接口使用蓝牙适配器,需要选择

HCI USB driver

2.2        Bluez Lib / Utils

Bluez Lib的编译比较简单,而Bluez-Utils所依赖的库就比较多了,大体包括 dbus alsa hal gstreamer openobex xml等等,仔细观察./configure 的输出,将所需要的包先安装或者build好。

值得注意的一点是:

如果你需要打开所有的功能模块的支持,需要在 ./configure 参数中添加 –enable-all  –enable-audio –enable-input –enable-network –enable-serial 等,在3.22版本中 –enable-all 居然不包括 audio等相关模块的service的编译,不知道是否是因为还保留了daemon和service等不同方案的缘故。不过,这至少与他的 configure –help 对于 –enable-all 的描述是不符合的。

3         蓝牙硬件初始化及基础服务启动

如果在PC环境下,使用Ubuntu,调用 /etc/init.d/bluetooth start 应该就能完成这一步的工作了。下面叙述一下在我的嵌入式环境下,如何手动完成这一步骤。

3.1        何谓硬件初始化

硬件初始化,指的是配置蓝牙芯片,将其置于一个能够正常通讯的状态。

对于CSR的芯片来说,就是通过设置PSKEY,设置其晶振频率,UART波特率等等一些关键参数。 如果使用的是USB形式的适配器,因为其EEPROM存储了相关的默认参数,这一步很可能不需要做,而我使用的是不带EEPROM的ROM版本芯片,如何 正确完成初始化工作着实让我折腾了一阵。

对于其它芯片,没有太多研究,不过,据我有限的了解,TI的芯片在hciattach时也需要完成一些额外的初始化工作,其它如ST的芯片则可能需要下载firmware。

3.2        硬件初始化步骤

通常蓝牙芯片的初始化和协议绑定可以通过 hciattach 来完成(通过配置bluez的启动脚本,可以不需要使用hciattach,标准发行版应该都是不用hciattach,如何配置,还没有研究 。。。 8 )

Hciattach 需要的参数主要包括 TTY节点,设备类型,波特率等。多数类型的设备的初始化工作,在选择了正确的设备类型参数后,都由hciattach在init_uart函数中调用具体的初始化函数所完成。

很遗憾的是,因为要重新设置晶振频率和波特率,并同步BCSP协议,这种方式好像处理不了我所使用的芯片(不排除我没有找到正确的解决方案的可能 性),我最终的解决办法是在hciattach之前,使用Bluez-utils里的BCCMD工具先完成这些PSKEY的设置工作。

具体命令是:

bccmd -t bcsp -d /dev/ttyS1 psload -r csr.psr

在这时,由于HCI接口还没有启动,所以只能使用BCSP协议来进行通讯,我的设备是暴露在ttyS1下,你的可能不一样,-r参数指明在psload完成 PSKEY的批量加载操作之后,对芯片进行Warmreset,否则这些参数的修改不会起作用。

Csr.psr的内容取决与你的芯片,我的大致如下:

// PSKEY_ANA_FREQ

&01fe = 9C40 // 相当于40M的晶振

// PSKEY_UART_BAUD_RATE

&01be = 0EBF // 921600的波特率

// PSKEY_UART_SEQ_WINSIZE

&0407 = 0006

// BDADDR

&0001 = 1122 3344 5566 7788

。。。

这里有个问题,你会发现,通过bccmd -t bcsp psset 命令理论上应该是可以单步设置每一个PSKEY的,但是从我实践看来,单步的操作在两次对bccmd的调用过程中,上一次对PSKEY的修改,都会在下一 次调用之前被复位,从代码上看估计和BCSP协议的同步过程有关。

3.2.1          关于PSKEY的获取

如何获得正确的完整的PSKEY参数,大概会有几个途径:

?       通过CSR的网站下载boot_strap包,这是CSR自己的BCHS协议栈所使用的初始化代码,在里面找到你所需要的pskey值。

?       下载CSR的bluesuite工具,里面包含了一个叫pstool的工具,可以用它来读写CSR的Casira开发板或其它BT设备的PSKEY设置,试验并找出你能用的参数。

?       找CSR或模组厂商支持 8 )

不过,基本上来说,如果只是要让芯片通过串口能够和Bluez协议栈正常通讯上,只需要设置PSKEY_ANA_FREQ 和 PSKEY_UART_BAUD_RATE 这两个PSKEY就可以了。

3.3        Daemon进程的启动

早先的版本里,Bluez的Daemon很多,但是最近的版本,很多daemon都转为service的形式来做了,3.22 里面包括了以下这几个Service,其它profile貌似还保留着daemon的形式。

bluetoothd-service-serial

bluetoothd-service-network

bluetoothd-service-audio

bluetoothd-service-input

这几个Service的启动依赖于hcid的启动以及相关的配置文件

主要配置文件位于:/etc/bluetooth/

此外,通常还需要启动SDP来提供服务查询,另外,Bluez本身还依赖于Dbus daemon的运行。

所以,整体上来说,我的手动启动Bluez的全过程如下:(其中内核代码是以模块形式编译的)

insmod bluetooth.ko

insmod hci_uart.ko

insmod l2cap.ko

insmod rfcomm.ko

insmod sco.ko

insmod hidp.ko

/etc/rc2.d/S20dbus start

bccmd -t bcsp -d /dev/ttyS1 psload -r csr.psr

hciattach -s 921600 /dev/ttyS1 bcsp 921600

hciconfig hci0 up

sdpd

hcid –d

4         Paring配对

4.1        Passkey_agent

在正常使用一个蓝牙设备前,通常都需要对该设备进行配对绑定的操作。

Bluez的配对机制貌似也修改了几次,2.x版本中通过pin_helper来处理pin code的应答,3.22版本里使用的配对机制,其API是基于Dbus来实现的,需要向dbus注册一个agent,PC的发行版通常都会有一些基于各 种图形库的passkey_agent,对于嵌入式系统,这部分代码可以想象,应该是要按照相应的API自己实现一个,为了测试,我直接使用了 bluez-utils/daemon 目录下的passkey-agent

这是一个命令行下的可以使用预先设定的pin code进行配对的程序

为了使用它,我的文件系统里 /etc/Bluetooth/hcid.conf 中 option一节类似如下 :

# HCId options

options {

# Automatically initialize new devices

autoinit yes;

# Security Manager mode

#   none – Security manager disabled

#   auto – Use local PIN for incoming connections

#   user – Always ask user for a PIN

#

security user;

# Pairing mode

pairing multi;

# Do the same as “hciconfig hci0 down” when SetMode(“off”)

# is called.

offmode devdown;

# Default PIN code for incoming connections

passkey “1234″;

}

4.2        关于自动配对和请求的发起

配对的发起,这里主要是从请求的发起者是谁的角度来说。

通常可能不需要关心配对请求是由本地还是由远端发起的,使用passkey_agent都能够正确处理。

不过如果在hcid.conf中将 Security Manager mode 设置为 auto,则Bluez会将passkey后面的字符串作为默认的Pin code,自动答复远端发起的配对请求。这是在没有使用passkey_agent的情况下的一种配对方式。

在这种情况下,Bluez可以处理远端的配对请求,但是对于本地发起的配对请求,将无法正确处理,我没有仔细的分析原因,或许是代码特意设计成这种 工作方式。所以在无法明确知道谁将会主动先发起配对请求的情况下,使用Atuo模式,可能就会出现有些时候设备能绑定有些时候不能绑定的现象。

通常如果是由本地设备搜索发现的新设备,配对绑定的操作应该也是由本地发起。

另外可以观察到,对远端一个非PC类的蓝牙设备,如蓝牙耳机,如果上次绑定过,在耳机启动时会主动发起连接请求,如果本地的link key丢失了,也就会再走一次绑定的流程,这种情况下配对请求就是由远端设备发起的。

5         A2DP

A2DP蓝牙立体声应该是蓝牙最常见的Profile之一。

2.x版本的Bluez,对A2DP的支持是通过BTSCO来实现的,3.22的版本通过bluetoothd-service-audio来支持。

对Bluez A2DP profile的支持,还依赖于Alsa或Gstreamer。

5.1        配置

测试A2DP的时候,我使用的是aplay,同时在相关的配置文件里面写死了蓝牙耳机的地址

主要的配置文件包括:

/etc/asound.conf :

pcm.bluetooth{

type bluetooth

device 00:02:5B:00:C1:A0

profile “hifi”

}

/etc/bluetooth/audio.conf :

[General]

# disable=Sink

SCORouting=PCM

[Headset]

DisableHFP=true

[A2DP]

SourceCount=2

配置好这些以后,使用 aplay -D bluetooth sample.wav 进行测试。

值得注意的是,使用Aplay打开蓝牙设备进行播放,需要有如下两个Alsa的plugin:

/usr/lib/alsa-lib/libasound_module_pcm_bluetooth.so

/usr/lib/alsa-lib/libasound_module_ctl_bluetooth.so

这两个so文件可以在bluez-utils 里面找到。需要注意他们和libasound 的版本匹配。

5.2        问题

在测试中发现,如果连接的耳机是由PC上的蓝牙适配器提供的AV耳机服务,那么配对可以完成,但是连接会失败,真正的耳机则没有这个问题,不知道是 否是因为以上的方法还存在缺陷?尝试使用由DBUS发起命令的形式来连接PC的AV耳机服务,也是一样的问题。是否连接PC模拟的AV耳机服务,首先要切 换设备的role?

没有测试Ctl接口

如何动态选择不同的耳机,而不是写死在脚本里?(这个想来估计是要自己基于Alsa的API编程处理,aplay无法直接完成测试)

播放大文件会出现under run错误,需要测试是由与波特率设置不够高造成,还是SBC编码效率不够,还是这个版本里存在的bug。

6         DUN的使用

Dun profile运行于rfcomm之上,主要是通过蓝牙接口暴露一个Modem的接口,用于提供拨号上网服务。

在这里所讨论的不是提供拨号上网服务本身,而是使用外部设备所提供的这个服务,进行网络连接。

6.1        系统配置

通常为了使用DUN,或者任何一个其它类型的Modem,我们会通过PPP协议来拨号和建立网络连接。

首先需要内核的支持,可以简单的把 device drivers -> Network device support 下面的PPP相关的内容全部选上。

其次,要编译应用层的PPP包,我的测试是基于ppp-2.4.4

主要的两个ppp配置文件:

/etc/ppp/peers/gprs:

/dev/rfcomm0

115200

defaultroute

usepeerdns

nodetach

noauth

local

debug

connect “/usr/sbin/chat -v -f /etc/ppp/chat-gprs”

/etc/ppp/chat-gprs:

TIMEOUT 10

ABORT ‘BUSY’

ABORT ‘NO ANSWER’

ABORT ‘ERROR’

“” ‘ATZ’

SAY ‘Init….\n’

OK ‘AT+CGDCONT=1,”IP”,”CMWAP”‘

ABORT ‘NO CARRIER’

SAY ‘Dialing….\n’

OK ‘ATD*99***1#’

CONNECT ”

前面一个配置文件基本就是那样了,后面一个,这两句要根据你的SIM卡的实际情况来处理:

OK ‘AT+CGDCONT=1,”IP”,”CMWAP”‘

OK ‘ATD*99***1#’

这里我设置的是使用中国移动的CMWAP。

此外,使用CMWAP还需要设置你的浏览器的代理服务器:10.0.0.172 端口9201

6.2        连接步骤

首先是要查找提供dun服务的设备,将服务提供在哪个channel通道上。这可以通过sdptool来查看,在我的设备上查询的结果是在channel 1上:

~ # ./sdptool browse 00:08:C6:77:A0:6C

Browsing 00:08:C6:77:A0:6C …

Service Name: Dial-upnetworking

Service RecHandle: 0×10000

Service Class ID List:

“Dialup Networking” (0×1103)

“Generic Networking” (0×1201)

Protocol Descriptor List:

“L2CAP” (0×0100)

“RFCOMM” (0×0003)

Channel: 1

Profile Descriptor List:

“Dialup Networking” (0×1103)

Version: 0×0100

其次,如果rfcomm所需设备节点不存在,将其创建:

mknod -m 666 /dev/rfcomm0 c 216 0

然后就是拨号了,如果该设备之前没有绑定,这过程中会自动发起绑定操作:

pppd debug dump call gprs &

完成以后就可以看到 ppp0这样一个网络接口了。

~ # ifconfig

ppp0      Link encap:Point-to-Point Protocol

inet addr:10.154.76.82  P-t-P:192.200.1.21  Mask:255.255.255.255

UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1

RX packets:4 errors:0 dropped:0 overruns:0 frame:0

TX packets:6 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:3

RX bytes:64 (64.0 B)  TX bytes:101 (101.0 B)

7         Bluez相关的各种tools的使用

在这一段折腾Bluez的时间里,越来越发现Bluez相关的许多工具做得还是挺好用的,主要在Bluez-utils/tools 目录下。只是有一点让我很遗憾,除了man以外很难找到更多的帮助文档,而man文档本身对一些功能的描述也不是很详细。

其中有些选项,如果你不了解蓝牙协议栈,或者没有查阅过相关蓝牙芯片的一些文档,很难搞明白是什么意思,甚至有些选项的具体参数值的设定,如果不读源码你都无从得知有哪些备选值。。。。

能力有限,下面所写的只是我所用过的有限的几个工具的一些使用经验,希望能有所帮助。

7.1        Bccmd

Bccmd是用来和CSR的芯片进行BCCMD(Bluecore command protocol)通讯的一个工具。BCCMD并非蓝牙协议栈的标准,而是CSR芯片的专属协议

Bccmd的调用格式为:bccmd [-t <transport>] [-d <device>] <command> [<args>]

Tansport类型包括 HCI USB BCSP H4等,常用的估计就是HCI和BCSP两种。需要注意一下他们的使用场合:

HCI是一个抽象的标准的蓝牙通讯接口,在基于HCI协议调用BCCMD时,需要在Bluez已经建立好hci接口的基础上使用。

BCSP(Bluecore Serial Protocol)是CSR自己制定的传输层协议,主要目的是用来加强在没有使用CTS、RTS进行流量控制的情况下进行可靠的数据传输的能力。其概念是 相对H3 , H4而言,( 具体分析,请参考下面杂项一章中相应的小节 )

BCCMD的主要用途就是用来读写pskey,这里以 psset 这个command来介绍一下格式:

Psset 格式如下: psset [-r] [-s <stores>] <key> <value>

其它都好理解,关键是-s参数之后跟的store具体的含义。这个参数可以是数值也可以是字符串

查询CSR的BCCMD相关的文档,可以找到具体的含义如下:

0×0000 Default

0×0008 psram

0×0001 psi

0×0002 psf

0×0004 psrom

0×0003 psi then psf

0×0007 psi, psf then psrom

0×0009 psram then psi

0x000b psram, psi then psf

0x000f psram, psi, psf then psrom

CSR的蓝牙芯片中,PSKEY可能存储在 rom flash eeprom ram等介质里,这里的数值指明了psset/get命令操作PSKEY时所针对的存储介质及其优先顺序,通常我们会用 –s 0×0 或 –s “default” 来使用该命令,0×0的含义与0xf一样。

值得注意的是,哪个参数是有效的,还取决于哪一类的存储介质实际存在于蓝牙芯片中,此外,只读类的介质对写操作类的命令也是无效的。

基本上来说,所修改的都是位于psram中的pskey,此外,pskey修改以后要起作用,还要一并使用 –r参数,或直接用warmreset命令将蓝牙芯片进行warm reset。

7.2        Hciattach

Hciattach主要用来初始化蓝牙设备,它的命令格式如下:

hciattach [-n] [-p] [-b] [-t timeout] [-s initial_speed] <tty> <type | id> [speed] [flow|noflow] [bdaddr]

其中最重要的参数就是 type和speed,type决定了要初始化的设备的型号,可以使用 hciattach –l 来列出所支持的设备型号。

并不是所有的参数对所有的设备都是适用的,有些设备会忽略一些参数设置,例如:查看hciattach的代码就可以看到,多数设备都忽略bdaddr参数。

Hciattach命令内部的工作步骤是:首先打开制定的tty设备,然后做一些通用的设置,如flow等,然后设置波特率为 initial_speed,然后根据type调用各自的初始化代码,最后将波特率重新设置为speed。所以调用hciattach时,要根据你的实际 情况,设置好initial_speed和speed。

对于type BCSP来说,它的初始化代码只做了一件事,就是完成BCSP协议的同步操作,它并不对蓝牙芯片做任何的pskey的设置。同步操作的具体流程和规范可以参考CSR的相关文档: BCSP Link Establishment Protocol

7.3        其它

下面几个,使用了,但是没有太多研究

7.3.1          Hcidump

Hcidump不在bluez-utils包里,而是在单独的hcidump包里。主要用来分析捕获和分析HCI数据包,如果使用bluez过程中 出了什么问题,用hcidump往往可以发现一些出错的线索,原因。 参数很多,基本上hcidump –X –V 就可以帮你获得详细的经过格式解析的数据包。

7.3.2          Hcitool

主要用hcitool来scan远端的设备,显示设备地址,名称等。

例如:Hcitool scan, hcitool inq

7.3.3          Sdptool

主要用来浏览远端设备SDP服务,或者管理本地的SDPD维护的数据库。

常用的应该就是查找远端设备的服务了

例如:

sdptool browse 00:02:72:B0:00:26 浏览地址为00:02:72:B0:00:26的设备所提供的服务

sdptool search 0×1112 00:02:72:B0:00:26 查找地址为00:02:72:B0:00:26的设备上的Headset Audio Gateway服务。

./sdptool search 0×1112 00:02:72:B0:00:26

Class 0×1112

Inquiring …

Searching for 0×1112 on 00:02:72:B0:00:26 …

Service Name: Headset Audio Gateway

Service RecHandle: 0x1001d

Service Class ID List:

“Headset Audio Gateway” (0×1112)

“Generic Audio” (0×1203)

。。。

7.3.4          Hciconfig

这个就不用多说了,格式上很类似于ifconfig,用来设置HCI设备的参数

例如

hciconfig hci0 up 启动hci0接口

hciconfig hci0 iscan 使能位于hci0接口的蓝牙芯片的inquery scan模式(使得设备能被其它蓝牙设备发现)

8         杂项

8.1        使用Dbus-send进行测试

由于Bluez使用dbus进行进程间通讯,所以我们可以使用dbus-send命令直接发送命令进行一些查询,试验的工作。

Bluez每个Daemon或service所支持的Dbus接口API描述文本,可以在各自的目录下找到,例如Audio的API写在 audio/audio-api.txt中。

以Audio为例,可以参考 http://wiki.bluez.org/wiki/HOWTO/AudioDevices 中的描述

8.2        HCI、H4、USB、BCSP 之间的关系

个人理解,严格的说HCI和其它几种protocol并不是可以对比的同一层次的东西。

HCI protocol 并不考虑在实际传输载体以及其中的纠错等问题,只是一个抽象的传输层或叫做接口。USB,H3,H4等才是具体的transport layer(此外还有SD Transport layer)。HCI数据包需要附着在这些具体的Transport Layer的协议包中。

以BCSP为例,4种类型的HCI数据包各自使用了一个BCSP通道,做为这些通道的payload封装在BCSP的协议包里,需要通过TTY的 lldsic层走一次,并由hci_uart模块做相应的封装工作。而BCSP还通过其它通道支持其它的一些自定的Protocol。BCSP作为一个具 体的传输层协议,还支持了校验,同步等功能。

H4机制类似,SD和USB transport好像区别比较大一点。具体可以参考 Bluetooth Specification Volume 4.

8.3        BCSP数据包结构

HCI数据包的结构,在bluetooth的spec里面有详细定义,不过,CSR自己的BCSP,BCCMD等一系列协议,又添加了一堆的东西, 其中,HCI数据包是作为BCSP的payload,而BCCMD又是作为HCI的payload,所以测试过程中,发觉要分析清楚bluez通过 kernel最后到底往蓝牙芯片的串口发送了什么数据,特别是想要自己手工构建一串数据,着实要看上一堆spec,拼凑起来才能完成。

要具体学习分析一串命令,最好的办法,我能想到的就是修改bccmd的代码,将它传给串口的每一个字符串都打印出来,这样对照这spec看,事半功倍。

例如下面这条,是使用我修改后的bccmd指令。所做的操作是读取串口波特率的pskey:

./bccmd.dbg -t bcsp -d /dev/ttyS1 psget -s 0×0 0x01be

cmd : 00 fc 13 c2 00 00 09 00 01 00 03 70 00 00 be 01 01 00 00 00 00 00

c0 d1 65 01 c8 00 fc 13 c2 00 00 09 00 01 00 03 70 00 00 be 01 01 00 00 00 00 69 a6 c0

在这里 HCI的数据包是第一行,具体解释一下:

头4个字节是HCI Head,其中

00 fc :整体代表这是一个制造商自定义的命令。

13 :HCI命令长度为0×13。

C2 :包的内容是唯一的一个BCCMD数据包。

后面是BCCMD的Head

00 00 :这是一个GetReq命令

09 00 :BCCMD的命令9个word长度,及18字节

01 00 :seqno, 包的顺序标记 包1

03 70 :varid 7003, 表示这是对PSKEY的操作

00 00 :状态标志

再下来是BCCMD的payload

be 01 :0x01be 波特率PSKEY的index

01 00 :该PSKEY的长度为1

00 00 :strore 为 00

00 00 :该PSKEY的值,这里是发送读命令,所以填0

第二行的数据是将HCI包封装在了BCSP数据包里:

前面部分:c0 d1 65 01 c8 :

C0 :是BCSP数据包的分割符

D1 :类型为可靠链接数据流,有CRC校验

65 01 :channel 5 ( HCI CMD ), 长度为0×16

C8 :包头的校验

后面部分:69 a6 c0:

69 a6 :整个BCSP包的CRC校验

C0 :分隔符

其它命令类似的分析可得。

如果只是希望看到HCI命令本身,也可以用hcidump来看。这是上面的读pskey操作通过HCI接口操作的dump:

< HCI Command: Vendor (0x3f|0×0000) plen 19

BCCMD: Get req: len 9 seqno 1 varid 0×7003 status 0

PSKEY: key 0x01be len 1 stores 0×0000

UART_BAUDRATE: value 0 (0×0000)

8.4        Hid / Serial / HF / OBEX

这几个比较常用的profile,还没测试哪。。。。。。谁给我买个蓝牙鼠标玩玩?!

8.5        总的遗留问题

整体上,PC上实现的自动识别,自动启动服务的一整套脚本,还没有仔细研究。

分类: bluetooth 标签: bluetooth, bluez

Android Bluetooth Class summary

2010年3月24日 zooyoo 没有评论

Setting app related

BluetoothSettings is the Settings screen for Bluetooth configuration and connection management.

BluetoothDevicePreference is the preference type used to display each remote Bluetooth device in the Bluetooth Settings screen.

BluetoothDiscoverableEnabler is a helper to manage the “Discoverable” checkbox. It sets/unsets discoverability and keeps track of how much time until the the discoverability is automatically turned off.

BluetoothEnabler is a helper to manage the Bluetooth on/off checkbox preference. It is turns on/off Bluetooth and ensures the summary of the preference reflects the current state.

BluetoothEventRedirector receives broadcasts and callbacks from the Bluetooth API and dispatches the event on the UI thread to the right class in the Settings.

BluetoothNamePreference is the preference type for editing the device’s Bluetooth name. It asks the user for a name, and persists it via the Bluetooth API.

BluetoothPinDialog asks the user to enter a PIN for pairing with a remote Bluetooth device. It is an activity that appears as a dialog.

BluetoothPinRequest is a receiver for any Bluetooth pairing PIN request. It checks if the Bluetooth Settings is currently visible and brings up the PIN entry dialog. Otherwise it puts a Notification in the status bar, which can be clicked to bring up the PIN entry dialog.

ConnectSpecificProfilesActivity presents the user with all of the profiles for a particular device, and allows him to choose which should be connected (or disconnected).

LocalBluetoothDevice represents a remote Bluetooth device. It contains attributes of the device (such as the address, name, RSSI, etc.) and functionality that can be performed on the device (connect, pair, disconnect, etc.).

LocalBluetoothDeviceManager manages the set of remote Bluetooth devices.

LocalBluetoothManager provides a simplified interface on top of a subset of the Bluetooth API.

LocalBluetoothProfileManager is an abstract class defining the basic functionality related to a profile.

SettingsBtStatus is a helper class that contains constants for various status codes.

Framework realted

AtCommandHandler is handler interface for AtParser.

AtCommandResult represent the final response to an AT command line, and also  intermediate responses to a single command within a chained AT command line.

AtParser object accepts a new command line to parse via its process() method. It breaks each command line into one or more commands. Each command is parsed for name, type, and (optional) arguments, and an appropriate external handler method is called through the AtCommandHandler interface.

BluetoothCmeError: Constants for extended AT error codes specified by the Handsfree profile.

BluetoothAtPhonebook is helper for managing phonebook presentation over AT commands

BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP Service via IPC. Currently this class provides methods to connect to A2DP audio sinks.

BluetoothA2dpService

BluetoothAudioGateway listen’s for incoming RFCOMM connection for the headset / handsfree service.  This class is planned for deletion, in favor of a generic Rfcomm class.

BluetoothClass is static helper methods and constants to decode the device class bit vector returned by the Bluetooth API.

BluetoothDevice manages the local Bluetooth device. Scan for devices, create bondings, power up and down the adapter.

BluetoothDeviceService

BluetoothError: constant error codes

BluetoothEventLoop

BluetoothHeadset is public API for controlling the Bluetooth Headset Service. This includes both Bluetooth Headset and Handsfree (v1.5) profiles. The Headset service will  attempt a handsfree connection first, and fall back to headset.

BluetoothHandsfree: Bluetooth headset manager for the Phone app.

BluetoothHeadsetService extends Service, provides Bluetooth Headset and Handsfree profile, as a service in the Phone application.

BluetoothIntent contains constant intens for bluetooth.

Database is A low-level API to the Service Discovery Protocol (SDP) Database.

HeadsetBase is the base RFCOMM (service) connection for a headset or handsfree device.

RfcommSocket implements an API to the Bluetooth RFCOMM layer. An RFCOMM socket  is similar to a normal socket in that it takes an address and a port number. The difference is of course that the address is a Bluetooth-device address, and the port number is an RFCOMM channel.

ScoSocket: Simple SCO Socket. Currently in Android, there is no support for sending data over a SCO socket – this is managed by the hardware link to the Bluetooth Chip. This class is instead intended for management of the SCO socket lifetime,  and is tailored for use with the headset / handsfree profiles.

相关文章:

拥有「人类智能」的全球首款有「思想」的机器人,活细胞培养的神经元

出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 脑机接口&#xff0c;其主体是人的大脑&#xff0c;利用人大脑中产生的信号转换为命令而执行任务。 首款有思想的机器人&#xff1f;是的&#xff0c;你真的没有看错&#xff01; 反过来说呢&#xff0c;比如主体是机…

使用VS2010调试技巧让C指针无处遁形

Linux 下调试远没有windows下的VS方便&#xff0c;不管是VC6还是VS2003&#xff0c;2005&#xff0c;2008&#xff0c;2010&#xff0c;2012. VS2012自动格式化代码 CtrlKD VS下调试一定要注意尽量不要用F11&#xff0c;要用F10&#xff01;不然需要引入库文件&#xff0c;提示…

Maven就是这么简单

2019独角兽企业重金招聘Python工程师标准>>> 什么是Maven Maven是一个采用纯Java编写的开源项目管理工具, Maven采用了一种被称之为Project Object Model (POM)概念来管理项目&#xff0c;所有的项目配置信息都被定义在一个叫做POM.xml的文件中.. **Maven是一款跨平…

C语言的内联函数的作用

关内联函数键字inline void myprintf(int a){priintf("%d",a);}int main(){for(i0;i<100;i)myprintf(3);}对于这个函数&#xff0c;在进行反复的打印3的过程中我们是不是要反复的调用myprintf(int a)这个函数&#xff0c;进函数和出函数是需要时间的&#xff0c;假…

推荐 2个十分好用的 pandas 数据探索分析神器!

作者 | 俊欣来源 | 关于数据分析与可视化今天小编给大家推荐两款超好用的工具来对数据进行探索分析。更好地帮助数据分析师从数据集当中来挖掘出有用的信息PandasGUI一听到这个名字&#xff0c;大家想必就会知道这个工具是在Pandas的基础之上加了GUI界面&#xff0c;它所具备的…

DoubleViewPager

https://github.com/eltld/DoubleViewPager https://github.com/eltld/DoubleViewPagerSample

OCQ亮相中国移动办公峰会 荣获2017中国移动办公创新品牌

11月21日至23日&#xff0c;由中国软件网主办的“新格局 再出发——企服三会”在北京中关村软件园国际会议中心隆重举行!国内市场上移动办公、CRM、HR三大领域的主流企业参加会议&#xff0c;百位业界专家学者汇聚一堂&#xff0c;交流经验&#xff0c;碰撞思维&#xff0c;对三…

typedef和define具体的详细区别

1) #define是预处理指令&#xff0c;在编译预处理时进行简单的替换&#xff0c;不作正确性检查&#xff0c;不关含义是否正确照样带入&#xff0c;只有在编译已被展开的源程序时才会发现可能的错误并报错。例如&#xff1a; #define PI 3.1415926 程序中的&#xff1a;areaPI*r…

IOS初级:NSKeyedArchiver

NSKeyedArchiver对象归档 首先要实现<NScoding>里面的两个代理方法initWithCoder,encodeWithCoder property (nonatomic, copy) NSString *keyName; /*将某个对象写入文件时候会调用在这个方法中说清楚哪些属性需要存储*/ - (void)encodeWithCoder:(NSCoder *)encoder{[e…

「摸鱼」神器来了,Python 实现人脸监测制作神器

作者 | 李秋键 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 最近都在讨论工作摸鱼&#xff0c;网易云音乐也出了合理摸鱼时间表&#xff0c;今天给大家推荐如何用python实现摸鱼~码住呦&#xff01; 引言&#xff1a;脸部表情是人类情绪的最直接外部表现之一和进…

初学Java——选择

1.boolean数据类型 1)取值为true/false 2)关系操作符的运算结果是boolean类型&#xff08;6种关系运算符同C语言&#xff09;2.分支语句 1)单分支if 2)双分支if-else 3)多分支if-else(此编码风格可避免深度缩进) if(){ } else if(){ } else if(){ } …

C语言宏定义使用技巧

写好C语言&#xff0c;漂亮的宏定义很重要&#xff0c;使用宏定义可以防止出错&#xff0c;提高可移植性&#xff0c;可读性&#xff0c;方便性等等。下面列举一些成熟软件中常用得宏定义。。。。。。1&#xff0c;防止一个头文件被重复包含#ifndef COMDEF_H#define COMDEF_H//…

java显示本地磁盘所有盘符,显示桌面路径

import java.io.File; import javax.swing.filechooser.FileSystemView;/** 显示本地磁盘根盘符&#xff0c;显示桌面路径 */ public class RDDemo {static File[] files;public static void main(String[] args) {FileSystemView sys FileSystemView.getFileSystemView();fil…

Twitter 禁止未经用户同意分享照片和视频

整理 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; Twitter 宣布将扩大私人信息政策&#xff0c;包括在未经个人许可的情况下共享的私人媒体&#xff0c;例如照片和视频&#xff0c;因为该社交媒体平台旨在改善用户隐私和安全。 “分享个人媒体&#xff…

这就是我向您推荐使用Thunderbird邮件客户端的理由

E-MAIL服务是最古老的互联网服务之一&#xff0c;相信很多人都在使用&#xff0c;只不过频率不同。IM出现后的&#xff08;及时通信工具&#xff09;一段时间&#xff0c;E-MAIL的通信不及时性估计让很多人交流会更倾向于IM。但是电子邮件&#xff08;E-MAIL&#xff09;仍然是…

ATT汇编语言与GCC内嵌汇编简介

AT&T汇编语言与GCC内嵌汇编简介1 AT&T 与INTEL的汇编语言语法的区别1.1大小写1.2操作数赋值方向1.3前缀1.4间接寻址语法1.5后缀1.6指令2 GCC内嵌汇编2.1简介2.2内嵌汇编举例2.3语法2.3.1汇编语句模板2.3.2输出部分2.3.3输入部分2.3.4限制字符2.3.5破坏描述部分2.4GCC如…

递归和迭代之间的差

递归的基本概念:编程技巧程序调用自身递归调用,是一个函数&#xff0c;调用自身. 在一个函数的定义直接或间接调用自己的方法,它通常是一个大的&#xff0c;复杂的问题分解成一个需要解决的问题类似于原来小问题,它可以大大减少的代码量.使用递归的能力是有限的语句来定义对象的…

智能交通:影响人类未来10-40年的重大变革

作者 | 百度创始人、董事长兼CEO李彦宏 《智能交通&#xff1a;影响人类未来10—40年的重大变革》&#xff0c;是我写的第三本关于人工智能的书。第一本是2017年编写的《智能革命&#xff1a;迎接人工智能时代的社会、经济与文化变革》&#xff0c;第二本是2020年编写的《智能…

Python--日志模块

# 时间 哪个文件里面的 第几行代码import loggingfrom logging import handlers# logging.debug(debug级别&#xff0c;最低级别&#xff0c;一般开发人员用来打印一些调试信息)# logging.info(info级别&#xff0c;正常输出信息&#xff0c;一般用来打印一些正常的操作)# logg…

Linux动态库(.so)搜索路径

众所周知&#xff0c;Linux动态库的默认搜索路径是/lib和/usr/lib。动态库被创建后&#xff0c;一般都复制到这两个目录中。当程序执行时需要某动态库&#xff0c;并且该动 态库还未加载到内存中&#xff0c;则系统会自动到这两个默认搜索路径中去查找相应的动态库文件&#xf…

redis-3.0.2集群部署

Redis 集群安装集群搭建步骤1、创建多个节点.2、为每个节点指派槽&#xff0c;并将多个节点连接起来&#xff0c;组成一个集群.3、当集群数据库的16384个槽都有节点在处理时&#xff0c;集群进入上线状态.要求&#xff1a;搭建一个包含6个节点的Redis集群&#xff0c;其中三个主…

联邦学习应用思考:需求还是方法?

作者 | 徐葳 清华大学交叉信息研究院长聘副教授、华控清交首席科学家前言&#xff1a;目前&#xff0c;“联邦学习”这个术语在市场上存在很多认识上的误解和混淆&#xff0c;主要原因是其既在广义上表达了保护数据前提下联合多方数据训练模型的需求&#xff0c;又在狭义上表示…

monkey如何获取app包名

别人学习网址&#xff1a;http://www.51testing.com/html/58/15092658-2984032.html 使用aapt aapt是sdk自带的一个工具&#xff0c;在sdk\builds-tools\目录下&#xff0c; 1. 在cmd中&#xff0c;切换至sdk\builds-tools\目录下&#xff0c;即aapt.exe目录下2.以QQ音乐为例…

嵌入式Web服务器移植

第一步 Boa程序的移植1、下载Boa源码下载地址: http://www.boa.org/&#xff0c; 或者http://sourceforge.net最新发行版本&#xff1a; 0.94.13下载 boa-0.94.13.tar.gz&#xff0c;注意&#xff1a;从boa上下载的是boa-0.94.13.tar.tar&#xff0c;解压方式一样解压&#xff…

一文详解 RNN 及股票预测实战(Python)!

作者 | 泳鱼来源 | 算法进阶循环神经网络&#xff08;RNN&#xff09;是基于序列数据&#xff08;如语言、语音、时间序列&#xff09;的递归性质而设计的&#xff0c;是一种反馈类型的神经网络&#xff0c;其结构包含环和自重复&#xff0c;因此被称为“循环”。它专门用于处理…

symfony2 Process 组件的学习笔记

2019独角兽企业重金招聘Python工程师标准>>> 安装 composer require "symfony/process:2.7.1" ##描述 process组件是可以开启一个子进程 去执行一个命令 ##例子 use Symfony\Component\Process\Process; $process new Process(ls -lsa); $process->ru…

C++模式学习------策略模式

当遇到同一个对象有不同的行为&#xff0c;方法&#xff0c;为管理这些方法可使用策略模式。 策略模式就是对算法进行包装&#xff0c;是把使用算法的责任和算法本身分割开来。通常把一个系列的算法包装到一系列的策略类里面&#xff0c;这些类继承一个抽象的策略类。使用这些算…

自动生成Makefile的全过程详解

automake/autoconf入门作为Linux下的程序开发人员&#xff0c;大家一定都遇到过Makefile&#xff0c;用make命令来编译自己写的程序确实是很方便。一般情况下&#xff0c;大家都是手工写一个简单Makefile&#xff0c;如果要想写出一个符合自由软件惯例的Makefile就不那么容易了…

Meta 开移动端 AI 生成神器 PyTorch Live,打造人工智能驱动的移动体验

整理 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 近日&#xff0c;PyTorch 开发者大会如期召开。在会上&#xff0c;Meta 发布了PyTorch Live&#xff0c;这是一套可以为移动端用户提供人工智能体验的工具。PyTorch Live 支持单一的编程语言JavaScript…

在NewLisp中实现匿名函数的递归

2019独角兽企业重金招聘Python工程师标准>>> 匿名函数在很多语言中的表现形式大概如下&#xff1a; (lambda (n)(* ( n 1) (- n 1))) 只有参数列表和函数体&#xff0c;而没有名字。在大部分情况下没问题&#xff0c;但是一旦需要用到递归的话&#xff0c;就有点麻烦…