﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-luofuchong</title><link>http://www.cnitblog.com/luofuchong/</link><description /><language>zh-cn</language><lastBuildDate>Sun, 05 Jul 2009 20:54:18 GMT</lastBuildDate><pubDate>Sun, 05 Jul 2009 20:54:18 GMT</pubDate><ttl>60</ttl><item><title>phoneme移植</title><link>http://www.cnitblog.com/luofuchong/archive/2009/04/28/56799.html</link><dc:creator>lfc</dc:creator><author>lfc</author><pubDate>Tue, 28 Apr 2009 08:42:00 GMT</pubDate><guid>http://www.cnitblog.com/luofuchong/archive/2009/04/28/56799.html</guid><wfw:comment>http://www.cnitblog.com/luofuchong/comments/56799.html</wfw:comment><comments>http://www.cnitblog.com/luofuchong/archive/2009/04/28/56799.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luofuchong/comments/commentRss/56799.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luofuchong/services/trackbacks/56799.html</trackback:ping><description><![CDATA[方法一：<br><span style="font-weight: bold;"><br></span>注：<br>&nbsp;&nbsp;&nbsp; 参考《<font style="font-size: 14pt;" color="#295200">phoneme feature移植》</font>一贴<br><br>1、编译脚本(MakefileFB):<span style="font-weight: bold;"><br><br></span>export ME_ROOT=${HOME}/work/svn/phoneME<br>export COMPONENTS_DIR=$(ME_ROOT)<br>export Scripts=`pwd`<br>export Output=$(ME_ROOT)/outputfb<br>export Log=$(ME_ROOT)/log.txt<br>export JDK_DIR=/usr/local/jdk1.6.0_13<br>export GNU_TOOLS_DIR=/usr/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux/arm-linux<br>export DIRECTFB_INSTALL_DIR=/usr/local/directfb<br>export USE_DEBUG_ROMGEN=true<br>export USE_DEBUG_ROMGEN_SYMBOLS=true<br>export USE_JSR_293 = false<br><br>all : dump pcsl1s pcsl2s cldc midp<br>dump :<br>&nbsp;&nbsp;&nbsp; @echo "---------start build phoneME feature--------------------"<br><br>pcsl1s ::<br>&nbsp;&nbsp;&nbsp; @echo "---------build pcsl1s-----------------------------------"<br>&nbsp;&nbsp;&nbsp; make -C $(ME_ROOT)/pcsl \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PCSL_PLATFORM=linux_i386_gcc \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PCSL_OUTPUT_DIR=$(Output)/pcsl \<br>&nbsp;&nbsp;&nbsp; NETWORK_MODULE=bsd/generic \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TOOLS_DIR=$(ME_ROOT)/tools \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TOOLS_OUTPUT_DIR=$(Output)/tools <br><br>pcsl2s ::<br>&nbsp;&nbsp;&nbsp; @echo "---------build pcsl2s-----------------------------------"<br>&nbsp;&nbsp;&nbsp; make -C $(ME_ROOT)/pcsl \<br>&nbsp;&nbsp;&nbsp; PCSL_PLATFORM=linux_arm_gcc \<br>&nbsp;&nbsp;&nbsp; PCSL_OUTPUT_DIR=$(Output)/pcsl \<br>&nbsp;&nbsp;&nbsp; NETWORK_MODULE=bsd/generic \<br>&nbsp;&nbsp;&nbsp; TOOLS_DIR=$(ME_ROOT)/tools \<br>&nbsp;&nbsp;&nbsp; TOOLS_OUTPUT_DIR=$(Output)/tools \<br><br>cldc ::<br>&nbsp;&nbsp;&nbsp; @echo "---------build cldc-----------------------------------"<br>&nbsp;&nbsp;&nbsp; make -C $(ME_ROOT)/cldc/build/linux_arm \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; JDK_DIR=$(JDK_DIR) \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ENABLE_PCSL=true \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PCSL_OUTPUT_DIR=$(Output)/pcsl \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; JVMWorkSpace=$(ME_ROOT)/cldc \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; JVMBuildSpace=$(Output)/cldc \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; TOOLS_DIR=$(ME_ROOT)/tools \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; TOOLS_OUTPUT_DIR=$(Output)/tools<br><br>midp ::<br>&nbsp;&nbsp;&nbsp; @echo "---------midp----------------------------------------"<br>&nbsp;&nbsp;&nbsp; make -C $(ME_ROOT)/midp/build/linux_fb_gcc \<br>&nbsp;&nbsp;&nbsp; GNU_TOOLS_DIR=$(GNU_TOOLS_DIR) \<br>&nbsp;&nbsp;&nbsp; JDK_DIR=$(JDK_DIR) \<br>&nbsp;&nbsp;&nbsp; PCSL_OUTPUT_DIR=$(Output)/pcsl \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; CLDC_DIST_DIR=$(Output)/cldc/linux_arm/dist \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; TOOLS_DIR=$(ME_ROOT)/tools \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; TOOLS_OUTPUT_DIR=$(Output)/tools \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; MIDP_OUTPUT_DIR=$(Output)/midp \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; USE_DEBUG=true \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; CPU=arm<br><br>clean:&nbsp;&nbsp;&nbsp; jclean pclean cclean mclean<br><br>jclean :<br>&nbsp;&nbsp;&nbsp; rm -rdf $(Output)/javacall<br>pclean :<br>&nbsp;&nbsp;&nbsp; rm -rdf $(Output)/pcsl1s<br>&nbsp;&nbsp;&nbsp; rm -rdf $(Output)/pcsl2s<br>cclean :<br>&nbsp;&nbsp;&nbsp; rm -rdf $(Output)/cldc<br>mclean :<br>&nbsp;&nbsp;&nbsp; rm -rdf $(Output)/midp<br><br>2、使用方法：<br>&nbsp;&nbsp;&nbsp; make clean -f MakefileFB<br>&nbsp;&nbsp;&nbsp; make -f MakefileFB<br><br><br>方法二：<br><br>1、编译脚本(build-phoneme):<span style="font-weight: bold;"><br></span><br>#!/bin/bash<br><br>#==========================================================<br># Figure out which component to build for which platform<br>#==========================================================<br>COMPONENT="none"<br>TARGET_PLATFORM="i386"<br>#CROSS_COMPILE=arm-none-linux-gnueabi-<br><br>if [ $# -gt 0 ]<br>then<br>COMPONENT=$1<br>fi<br><br>if [ $# -eq 2 ]<br>then<br>TARGET_PLATFORM=$2<br>fi<br><br>#==========================================================<br># Setup some environment variables and create dirs.<br>#==========================================================<br>export MEHOME=${HOME}/work/svn/phoneME<br>export LOG=$MEHOME/log.txt<br>export BUILD_OUTPUT_DIR=$MEHOME/build-$TARGET_PLATFORM<br>export JDK_DIR=${HOME}/work/java/jdk1.6.0_13<br>#export GNU_TOOLS_DIR=${HOME}/work/toolchain/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi<br><br>if [ "$TARGET_PLATFORM" = "arm" ]<br>then<br>echo<br>echo "Building for ARM"<br>echo<br>export PCSL_PLATFORM=linux_arm_gcc<br>export GNU_TOOLS_DIR=${HOME}/work/toolchain/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi<br>CROSS_COMPILE=arm-none-linux-gnueabi-<br>else<br>echo<br>echo "Building for i386"<br>echo<br>export PCSL_PLATFORM=linux_i386_gcc<br>export GNU_TOOLS_DIR=/usr<br>CROSS_COMPILE=<br>fi<br><br>if ! [ -d $BUILD_OUTPUT_DIR ]<br>then<br>mkdir $BUILD_OUTPUT_DIR<br>fi<br><br>#==========================================================<br># Build PCSL<br>#==========================================================<br>if [ "$COMPONENT" = "pcsl" ]<br>then<br>export PCSL_OUTPUT_DIR=$BUILD_OUTPUT_DIR/pcsl<br>cd $MEHOME/pcsl<br><br>if [ "$TARGET_PLATFORM" = "i386" ]<br>then<br>make NETWORK_MODULE=bsd/generic<br>else<br>make NETWORK_MODULE=bsd/generic \<br>CC='$(CROSS_COMPILE)gcc' \<br>CPP='$(CROSS_COMPILE)g++' \<br>AR='$(CROSS_COMPILE)ar cqs' \<br>LD='$(CROSS_COMPILE)ld'<br>fi<br>fi<br><br>#==========================================================<br># Build PCSL documentation<br>#==========================================================<br>if [ "$COMPONENT" = "pcsl-doc" ]<br>then<br>cd $MEHOME/pcsl &amp;&amp;\<br>make doc<br>fi<br><br>#==========================================================<br># Build CLDC<br>#==========================================================<br>if [ "$COMPONENT" = "cldc" ]<br>then<br>export JVMWorkSpace=$MEHOME/cldc<br>export JVMBuildSpace=$BUILD_OUTPUT_DIR/cldc<br><br>if [ "$TARGET_PLATFORM" = "i386" ]<br>then<br>cd $JVMWorkSpace/build/linux_i386<br>make ENABLE_PCSL=true \<br>ENABLE_ARM_V7=true \<br>PCSL_OUTPUT_DIR=$BUILD_OUTPUT_DIR/pcsl \<br>ENABLE_ISOLATES=true<br>else<br>cd $JVMWorkSpace/build/linux_arm<br>make ENABLE_PCSL=true \<br>PCSL_OUTPUT_DIR=$BUILD_OUTPUT_DIR/pcsl \<br>CC='$(CROSS_COMPILE)gcc' \<br>CPP='$(CROSS_COMPILE)g++' \<br>AR='$(CROSS_COMPILE)ar cqs' \<br>LD='$(CROSS_COMPILE)ld'<br>fi<br>fi<br><br>#==========================================================<br># Build CLDC documentation<br>#==========================================================<br>if [ "$COMPONENT" = "cldc-doc" ]<br>then<br>export JVMWorkSpace=$MEHOME/cldc<br>cd $JVMWorkSpace/build/linux_i386<br>make docs_html<br>fi<br><br>#==========================================================<br># Build MIDP<br>#==========================================================<br>if [ "$COMPONENT" = "midp" ]<br>then<br>export MIDP_OUTPUT_DIR=$BUILD_OUTPUT_DIR/midp<br><br>if [ "$TARGET_PLATFORM" = "i386" ]<br>then<br>cd $MEHOME/midp/build/linux_fb_gcc<br>make PCSL_OUTPUT_DIR=$BUILD_OUTPUT_DIR/pcsl \<br>CLDC_DIST_DIR=$BUILD_OUTPUT_DIR/cldc/linux_i386/dist \<br>TOOLS_DIR=$MEHOME/tools \<br>TARGET_CPU=i386 \<br>USE_MULTIPLE_ISOLATES=true<br>else<br>make PCSL_OUTPUT_DIR=$BUILD_OUTPUT_DIR/pcsl CLDC_DIST_DIR=$BUILD_OUTPUT_DIR/cldc/linux_arm/dist TOOLS_DIR=$MEHOME/tools TARGET_CPU=arm USE_MULTIPLE_ISOLATES=true CC='$(CROSS_COMPILE)gcc' CPP='$(CROSS_COMPILE)g++' AR='$(CROSS_COMPILE)ar cqs' LD='$(CROSS_COMPILE)ld'<br>fi<br>fi<br><br>echo<br>echo "======================================"<br>echo "FINISHED"<br>echo<br><br>2、使用方法：<br>./build-phoneme pcsl arm<br>./build-phoneme cldc arm<br><br><br> <img src ="http://www.cnitblog.com/luofuchong/aggbug/56799.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luofuchong/" target="_blank">lfc</a> 2009-04-28 16:42 <a href="http://www.cnitblog.com/luofuchong/archive/2009/04/28/56799.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>qt4交叉编译</title><link>http://www.cnitblog.com/luofuchong/archive/2009/04/25/56704.html</link><dc:creator>lfc</dc:creator><author>lfc</author><pubDate>Sat, 25 Apr 2009 03:44:00 GMT</pubDate><guid>http://www.cnitblog.com/luofuchong/archive/2009/04/25/56704.html</guid><wfw:comment>http://www.cnitblog.com/luofuchong/comments/56704.html</wfw:comment><comments>http://www.cnitblog.com/luofuchong/archive/2009/04/25/56704.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/luofuchong/comments/commentRss/56704.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luofuchong/services/trackbacks/56704.html</trackback:ping><description><![CDATA[1、qtopia-core-opensource-src-4.3.5:<br><br>&nbsp;&nbsp;&nbsp; ./configure -embedded arm -xplatform qws/linux-arm-g++ -depths 4,8,16,32 -no-qt3support -prefix /home/luofc/work/qt/target -fast -qt-sql-sqlite -no-libtiff -no-libmng -qt-libjpeg -qt-zlib -qt-libpng -qt-freetype -optimized-qmake -no-nis -no-separate-debug-info -no-qvfb -qt-gfx-linuxfb -no-gfx-qvfb -qt-kbd-usb -no-kbd-qvfb -no-mouse-qvfb -no-mouse-linuxtp -qt-mouse-pc -qt-mouse-tslib -I/home/luofc/work/qt/tslib/include -L/home/luofc/work/qt/tslib/lib<br><br>2、qtopia-opensource-4.2.4<br><br>&nbsp;&nbsp;&nbsp; ../source/qtopia-opensource-4.2.4/configure -debug -image /opt/qtopia -prefix /opt/qtopia -xplatform linux-arm-g++ -arch arm -no-qvfb -displaysize 480x272 -no-modem -no-bluetooth -no-infrared -extra-qtopiacore-config "-debug -xplatform qws/linux-arm-g++ -embedded arm -depths 4,8,16,32 -no-qt3support -fast -qt-sql-sqlite -no-libmng -qt-libjpeg -qt-zlib -qt-libpng -qt-freetype -no-nis -no-separate-debug-info -no-qvfb -qt-gfx-linuxfb -no-gfx-qvfb -qt-kbd-usb -no-kbd-qvfb -no-mouse-qvfb -no-mouse-linuxtp -qt-mouse-pc -qt-mouse-tslib -I/home/lfc/work/qt/tslib/include -L/home/lfc/work/qt/tslib/lib" 2&gt;configure_error.log<br><br>后注：<br>&nbsp;&nbsp;&nbsp; 使用arm-none-linux-gnueabi的编译器，qtopia-core-opensource编译后使用正常，qtopia-opensource编译成release的话，部分程序(包括qpe)运行的时候提示Segmentation fault错误，如果编译成debug的话，运行还算正常，可是要占用226M的空间，真是无语～<br> <img src ="http://www.cnitblog.com/luofuchong/aggbug/56704.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luofuchong/" target="_blank">lfc</a> 2009-04-25 11:44 <a href="http://www.cnitblog.com/luofuchong/archive/2009/04/25/56704.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】ARM平台上蓝牙协议栈Bluez的移植使用和配置 </title><link>http://www.cnitblog.com/luofuchong/archive/2009/04/23/56637.html</link><dc:creator>lfc</dc:creator><author>lfc</author><pubDate>Thu, 23 Apr 2009 03:57:00 GMT</pubDate><guid>http://www.cnitblog.com/luofuchong/archive/2009/04/23/56637.html</guid><wfw:comment>http://www.cnitblog.com/luofuchong/comments/56637.html</wfw:comment><comments>http://www.cnitblog.com/luofuchong/archive/2009/04/23/56637.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luofuchong/comments/commentRss/56637.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luofuchong/services/trackbacks/56637.html</trackback:ping><description><![CDATA[ARM平台上蓝牙协议栈Bluez的移植使用和配置
<br>作者：刘旭晖 Raymond转载请注明出处
<br>Email：colorant@163.com
<br>BLOG：http://blog.csdn.net/colorant/
<br>主页：http://rgbbones.googlepages.com/
<br>
<br>Bluez作为当前最成熟的开源蓝牙协议栈，在Linux的各大发行版中已经得到了广泛的应用。在桌面环境下，使用Bluez应该已经没有太大的
问题，本文的主要目的是介绍在嵌入式平台上，搭建和配置Bluez的各个Profile运行所需做的工作，讨论可能遇到的问题，介绍一些工具的使用和工作
原理。因为本人的能力和测试时间有限，可能下文中有些理解、分析不一定准确，欢迎联系指正。
<br>
<br>
<br>1	相关说明
<br>1.1	网站资源
<br>Bluez的官方网址：http://www.bluez.org/ 这里提供最新的源码下载，最近服务器崩溃了一次，有些东西没了。。。。
<br>Bluez的Wiki：http://wiki.bluez.org/wiki/ 这里提供Bluez相关的Howto等文档资源
<br>相关邮件列表：
<br><a  href="https://lists.sourceforge.net/lists/listinfo/bluez-users" target="_blank">https://lists.sourceforge.net/lists/listinfo/bluez-users</a> 关于如何使用和配置Bluez，多数是在讨论PC环境下的问题。。。。
<br><a  href="https://lists.sourceforge.net/lists/listinfo/bluez-devel" target="_blank">https://lists.sourceforge.net/lists/listinfo/bluez-devel</a> Bluez开发者活动的地方，有什么Bug之类的怀疑，还有编程接口之类的问题，就发到这里吧。
<br>
<br>1.2	工作环境
<br>个人感觉，使用Bluez最大的问题就是文档的欠缺，除了Wiki上的有限资料以外，很难找到其它有用的文档。
<br>由于Bluez的代码实现更新变化得很快，网上的许多文档介绍的都是早期版本的使用，再有的文章多数是基于成熟的Linux发行版，来讨论蓝牙设备的配置和使用，对于嵌入系统开发，自己编译，搭建和配置相关环境的文章很少。此外和具体蓝牙芯片相关的资料也很难找到。
<br>
<br>这里我不打算也没有能力写一个完整的指南，只能基于前段时间在自己的板子上所做的工作，总结一下相关的步骤和所遇到的各类问题以及这期间所掌握的各种相关知识。希望能给有类似开发需求的朋友一些有益的帮助，下面是这篇文章所基于的工作环境：
<br>
<br>&#61656;	硬件平台：基于ARM的嵌入式板子
<br>&#61656;	蓝牙芯片：CSR BC4 ROM 版本芯片，不带eeprom
<br>&#61656;	软件环境：Linux 2.6.21 ，自制文件系统
<br>&#61656;	Bluez版本：bluez-libs 3.22  bluez-utils 3.22
<br>
<br>2	编译
<br>2.1	内核
<br>相信多数人使用的都是2.6的内核了，在2.6的内核中要支持Bluez，只要你的内核版本不是太旧，无需打Patch，直接配置好就OK了，内
核里面的代码相对比较稳定了。当然，Bluez对一些Bluetooth协议栈新特性的支持，还是需要更新kernel代码的。你应该确认你使用的
kernel版本是否以及包含了对应的支持。
<br>
<br>内核的配置，基本上把 networking下 --- Bluetooth subsystem support 里的以下几项全部选上即可：
<br>
<br>L2CAP protocol support
<br>SCO links support
<br>RFCOMM protocol support
<br>RFCOMM TTY support
<br>BNEP protocol support
<br>HIDP protocol support
<br>
<br>此外，在Bluetooth device drivers里选上你所需要支持的Bluetooth设备。我使用的CSR的chip是我们直接build在板子上，通过串口和cpu通讯的，芯片默认使用BCSP作为通讯协议，所以我选择了：
<br>
<br>HCI UART driver
<br>BCSP protocol support
<br>
<br>如果你是通过usb接口使用蓝牙适配器，需要选择
<br>HCI USB driver
<br>
<br>2.2	Bluez Lib / Utils
<br>
<br>Bluez Lib的编译比较简单，而Bluez-Utils所依赖的库就比较多了，大体包括 dbus alsa hal gstreamer openobex xml等等，仔细观察./configure 的输出，将所需要的包先安装或者build好。
<br>值得注意的一点是：
<br>如果你需要打开所有的功能模块的支持，需要在 ./configure 参数中添加 --enable-all --enable-audio
--enable-input --enable-network &#8211;enable-serial 等，在3.22版本中 --enable-all
居然不包括
audio等相关模块的service的编译，不知道是否是因为还保留了daemon和service等不同方案的缘故。不过，这至少与他的
configure --help 对于 --enable-all 的描述是不符合的。
<br>
<br>3	蓝牙硬件初始化及基础服务启动
<br>
<br>如果在PC环境下，使用Ubuntu，调用 /etc/init.d/bluetooth start 应该就能完成这一步的工作了。下面叙述一下在我的嵌入式环境下，如何手动完成这一步骤。
<br>
<br>3.1	何谓硬件初始化
<br>硬件初始化，指的是配置蓝牙芯片，将其置于一个能够正常通讯的状态。
<br>
<br>对于CSR的芯片来说，就是通过设置PSKEY，设置其晶振频率，UART波特率等等一些关键参数。
如果使用的是USB形式的适配器，因为其EEPROM存储了相关的默认参数，这一步很可能不需要做，而我使用的是不带EEPROM的ROM版本芯片，如何
正确完成初始化工作着实让我折腾了一阵。
<br>
<br>对于其它芯片，没有太多研究，不过，据我有限的了解，TI的芯片在hciattach时也需要完成一些额外的初始化工作，其它如ST的芯片则可能需要下载firmware。
<br>
<br>3.2	硬件初始化步骤
<br>通常蓝牙芯片的初始化和协议绑定可以通过 hciattach 来完成（通过配置bluez的启动脚本，可以不需要使用hciattach，标准发行版应该都是不用hciattach，如何配置，还没有研究 。。。 8 ）
<br>
<br>Hciattach 需要的参数主要包括 TTY节点，设备类型，波特率等。多数类型的设备的初始化工作，在选择了正确的设备类型参数后，都由hciattach在init_uart函数中调用具体的初始化函数所完成。
<br>
<br>很遗憾的是，因为要重新设置晶振频率和波特率，并同步BCSP协议，这种方式好像处理不了我所使用的芯片（不排除我没有找到正确的解决方案的可能
性），我最终的解决办法是在hciattach之前，使用Bluez-utils里的BCCMD工具先完成这些PSKEY的设置工作。
<br>
<br>具体命令是：
<br>bccmd -t bcsp -d /dev/ttyS1 psload -r csr.psr
<br>
<br>在这时，由于HCI接口还没有启动，所以只能使用BCSP协议来进行通讯，我的设备是暴露在ttyS1下，你的可能不一样，-r参数指明在psload完成 PSKEY的批量加载操作之后，对芯片进行Warmreset，否则这些参数的修改不会起作用。
<br>
<br>Csr.psr的内容取决与你的芯片，我的大致如下：
<br>
<br>// PSKEY_ANA_FREQ
<br>&amp;01fe = 9C40 // 相当于40M的晶振
<br>// PSKEY_UART_BAUD_RATE
<br>&amp;01be = 0EBF // 921600的波特率
<br>// PSKEY_UART_SEQ_WINSIZE
<br>&amp;0407 = 0006
<br>// BDADDR
<br>&amp;0001 = 1122 3344 5566 7788
<br>。。。
<br>
<br>这里有个问题，你会发现，通过bccmd -t bcsp psset
命令理论上应该是可以单步设置每一个PSKEY的，但是从我实践看来，单步的操作在两次对bccmd的调用过程中，上一次对PSKEY的修改，都会在下一
次调用之前被复位，从代码上看估计和BCSP协议的同步过程有关。
<br>3.2.1	关于PSKEY的获取
<br>如何获得正确的完整的PSKEY参数，大概会有几个途径：
<br>&#61656;	通过CSR的网站下载boot_strap包，这是CSR自己的BCHS协议栈所使用的初始化代码，在里面找到你所需要的pskey值。
<br>&#61656;	下载CSR的bluesuite工具，里面包含了一个叫pstool的工具，可以用它来读写CSR的Casira开发板或其它BT设备的PSKEY设置，试验并找出你能用的参数。
<br>&#61656;	找CSR或模组厂商支持 8 ）
<br>
<br>不过，基本上来说，如果只是要让芯片通过串口能够和Bluez协议栈正常通讯上，只需要设置PSKEY_ANA_FREQ 和 PSKEY_UART_BAUD_RATE 这两个PSKEY就可以了。
<br>
<br>3.3	Daemon进程的启动
<br>早先的版本里，Bluez的Daemon很多，但是最近的版本，很多daemon都转为service的形式来做了，3.22 里面包括了以下这几个Service，其它profile貌似还保留着daemon的形式。
<br>bluetoothd-service-serial
<br>bluetoothd-service-network
<br>bluetoothd-service-audio
<br>bluetoothd-service-input
<br>这几个Service的启动依赖于hcid的启动以及相关的配置文件
<br>主要配置文件位于：/etc/bluetooth/
<br>此外，通常还需要启动SDP来提供服务查询，另外，Bluez本身还依赖于Dbus daemon的运行。
<br>
<br>所以，整体上来说，我的手动启动Bluez的全过程如下：（其中内核代码是以模块形式编译的）
<br>
<br>insmod bluetooth.ko
<br>insmod hci_uart.ko
<br>insmod l2cap.ko
<br>insmod rfcomm.ko
<br>insmod sco.ko
<br>insmod hidp.ko
<br>
<br>/etc/rc2.d/S20dbus start
<br>bccmd -t bcsp -d /dev/ttyS1 psload -r csr.psr
<br>hciattach -s 921600 /dev/ttyS1 bcsp 921600
<br>hciconfig hci0 up
<br>sdpd
<br>hcid &#8211;d
<br>
<br>4	Paring配对
<br>4.1	Passkey_agent
<br>在正常使用一个蓝牙设备前，通常都需要对该设备进行配对绑定的操作。
<br>Bluez的配对机制貌似也修改了几次，2.x版本中通过pin_helper来处理pin
code的应答，3.22版本里使用的配对机制，其API是基于Dbus来实现的，需要向dbus注册一个agent，PC的发行版通常都会有一些基于各
种图形库的passkey_agent，对于嵌入式系统，这部分代码可以想象，应该是要按照相应的API自己实现一个，为了测试，我直接使用了
bluez-utils/daemon 目录下的passkey-agent
<br>这是一个命令行下的可以使用预先设定的pin code进行配对的程序
<br>
<br>为了使用它，我的文件系统里 /etc/Bluetooth/hcid.conf 中 option一节类似如下 ：
<br>
<br># HCId options
<br>options {
<br>        # Automatically initialize new devices
<br>        autoinit yes;
<br>
<br>        # Security Manager mode
<br>        #   none - Security manager disabled
<br>        #   auto - Use local PIN for incoming connections
<br>        #   user - Always ask user for a PIN
<br>        #
<br>        security user;
<br>
<br>        # Pairing mode
<br>        pairing multi;
<br>
<br>        # Do the same as "hciconfig hci0 down" when SetMode("off")
<br>        # is called.
<br>        offmode devdown;
<br>
<br>        # Default PIN code for incoming connections
<br>        passkey "1234";
<br>}
<br>
<br>4.2	关于自动配对和请求的发起
<br>
<br>配对的发起，这里主要是从请求的发起者是谁的角度来说。
<br>
<br>通常可能不需要关心配对请求是由本地还是由远端发起的，使用passkey_agent都能够正确处理。
<br>
<br>不过如果在hcid.conf中将 Security Manager mode 设置为
auto，则Bluez会将passkey后面的字符串作为默认的Pin
code，自动答复远端发起的配对请求。这是在没有使用passkey_agent的情况下的一种配对方式。
<br>
<br>在这种情况下，Bluez可以处理远端的配对请求，但是对于本地发起的配对请求，将无法正确处理，我没有仔细的分析原因，或许是代码特意设计成这
种工作方式。所以在无法明确知道谁将会主动先发起配对请求的情况下，使用Atuo模式，可能就会出现有些时候设备能绑定有些时候不能绑定的现象。
<br>
<br>通常如果是由本地设备搜索发现的新设备，配对绑定的操作应该也是由本地发起。
<br>
<br>另外可以观察到，对远端一个非PC类的蓝牙设备，如蓝牙耳机，如果上次绑定过，在耳机启动时会主动发起连接请求，如果本地的link key丢失了，也就会再走一次绑定的流程，这种情况下配对请求就是由远端设备发起的。
<br>
<br>
<br>5	A2DP
<br>A2DP蓝牙立体声应该是蓝牙最常见的Profile之一。
<br>2.x版本的Bluez，对A2DP的支持是通过BTSCO来实现的，3.22的版本通过bluetoothd-service-audio来支持。
<br>对Bluez A2DP profile的支持，还依赖于Alsa或Gstreamer。
<br>5.1	配置
<br>测试A2DP的时候，我使用的是aplay，同时在相关的配置文件里面写死了蓝牙耳机的地址
<br>主要的配置文件包括：
<br>
<br>/etc/asound.conf ：
<br>
<br>pcm.bluetooth{
<br>        type bluetooth
<br>        device 00:02:5B:00:C1:A0
<br>        profile "hifi"
<br>}
<br>
<br>/etc/bluetooth/audio.conf ：
<br>
<br>[General]
<br># disable=Sink
<br>SCORouting=PCM
<br>
<br>[Headset]
<br>DisableHFP=true
<br>
<br>[A2DP]
<br>SourceCount=2
<br>
<br>配置好这些以后，使用 aplay -D bluetooth sample.wav 进行测试。
<br>
<br>值得注意的是，使用Aplay打开蓝牙设备进行播放，需要有如下两个Alsa的plugin：
<br>
<br>/usr/lib/alsa-lib/libasound_module_pcm_bluetooth.so
<br>/usr/lib/alsa-lib/libasound_module_ctl_bluetooth.so
<br>
<br>这两个so文件可以在bluez-utils 里面找到。需要注意他们和libasound 的版本匹配。
<br>
<br>5.2	问题
<br>在测试中发现，如果连接的耳机是由PC上的蓝牙适配器提供的AV耳机服务，那么配对可以完成，但是连接会失败，真正的耳机则没有这个问题，不知道
是否是因为以上的方法还存在缺陷？尝试使用由DBUS发起命令的形式来连接PC的AV耳机服务，也是一样的问题。是否连接PC模拟的AV耳机服务，首先要
切换设备的role？
<br>
<br>没有测试Ctl接口
<br>
<br>如何动态选择不同的耳机，而不是写死在脚本里？（这个想来估计是要自己基于Alsa的API编程处理，aplay无法直接完成测试）
<br>
<br>播放大文件会出现under run错误，需要测试是由与波特率设置不够高造成，还是SBC编码效率不够，还是这个版本里存在的bug。
<br>
<br>6	DUN的使用
<br>Dun profile运行于rfcomm之上，主要是通过蓝牙接口暴露一个Modem的接口，用于提供拨号上网服务。
<br>在这里所讨论的不是提供拨号上网服务本身，而是使用外部设备所提供的这个服务，进行网络连接。
<br>6.1	系统配置
<br>通常为了使用DUN，或者任何一个其它类型的Modem，我们会通过PPP协议来拨号和建立网络连接。
<br>首先需要内核的支持，可以简单的把 device drivers -&gt; Network device support 下面的PPP相关的内容全部选上。
<br>其次，要编译应用层的PPP包，我的测试是基于ppp-2.4.4
<br>
<br>主要的两个ppp配置文件：
<br>
<br>/etc/ppp/peers/gprs：
<br>
<br>/dev/rfcomm0
<br>115200
<br>defaultroute
<br>usepeerdns
<br>nodetach
<br>noauth
<br>local
<br>debug
<br>connect "/usr/sbin/chat -v -f /etc/ppp/chat-gprs"
<br>
<br>/etc/ppp/chat-gprs：
<br>
<br>TIMEOUT 10
<br>ABORT 'BUSY'
<br>ABORT 'NO ANSWER'
<br>ABORT 'ERROR'
<br>"" 'ATZ'
<br>SAY 'Init....\n'
<br>OK 'AT+CGDCONT=1,"IP","CMWAP"'
<br>ABORT 'NO CARRIER'
<br>SAY 'Dialing....\n'
<br>OK 'ATD*99***1#'
<br>CONNECT ''
<br>
<br>前面一个配置文件基本就是那样了，后面一个，这两句要根据你的SIM卡的实际情况来处理：
<br>
<br>OK 'AT+CGDCONT=1,"IP","CMWAP"'
<br>OK 'ATD*99***1#'
<br>
<br>这里我设置的是使用中国移动的CMWAP。
<br>
<br>此外，使用CMWAP还需要设置你的浏览器的代理服务器：10.0.0.172 端口9201
<br>
<br>6.2	连接步骤
<br>首先是要查找提供dun服务的设备，将服务提供在哪个channel通道上。这可以通过sdptool来查看，在我的设备上查询的结果是在channel 1上：
<br>
<br>~ # ./sdptool browse 00:08:C6:77:A0:6C
<br>
<br>Browsing 00:08:C6:77:A0:6C ...
<br>Service Name: Dial-upnetworking
<br>Service RecHandle: 0x10000
<br>Service Class ID List:
<br>  "Dialup Networking" (0x1103)
<br>  "Generic Networking" (0x1201)
<br>Protocol Descriptor List:
<br>  "L2CAP" (0x0100)
<br>  "RFCOMM" (0x0003)
<br>    Channel: 1
<br>Profile Descriptor List:
<br>  "Dialup Networking" (0x1103)
<br>    Version: 0x0100
<br>
<br>其次，如果rfcomm所需设备节点不存在，将其创建：
<br>
<br>mknod -m 666 /dev/rfcomm0 c 216 0
<br>
<br>然后就是拨号了，如果该设备之前没有绑定，这过程中会自动发起绑定操作：
<br>
<br>pppd debug dump call gprs &amp;
<br>
<br>完成以后就可以看到 ppp0这样一个网络接口了。
<br>
<br>~ # ifconfig
<br>ppp0      Link encap:Point-to-Point Protocol
<br>          inet addr:10.154.76.82  P-t-P:192.200.1.21  Mask:255.255.255.255
<br>          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
<br>          RX packets:4 errors:0 dropped:0 overruns:0 frame:0
<br>          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
<br>          collisions:0 txqueuelen:3
<br>          RX bytes:64 (64.0 B)  TX bytes:101 (101.0 B)
<br>
<br>7	Bluez相关的各种tools的使用
<br>在这一段折腾Bluez的时间里，越来越发现Bluez相关的许多工具做得还是挺好用的，主要在Bluez-utils/tools 目录下。只是有一点让我很遗憾，除了man以外很难找到更多的帮助文档，而man文档本身对一些功能的描述也不是很详细。
<br>其中有些选项，如果你不了解蓝牙协议栈，或者没有查阅过相关蓝牙芯片的一些文档，很难搞明白是什么意思，甚至有些选项的具体参数值的设定，如果不读源码你都无从得知有哪些备选值。。。。
<br>
<br>能力有限，下面所写的只是我所用过的有限的几个工具的一些使用经验，希望能有所帮助。
<br>7.1	Bccmd
<br>Bccmd是用来和CSR的芯片进行BCCMD（Bluecore command protocol）通讯的一个工具。BCCMD并非蓝牙协议栈的标准，而是CSR芯片的专属协议
<br>Bccmd的调用格式为：bccmd [-t &lt;transport&gt;] [-d &lt;device&gt;] &lt;command&gt; [&lt;args&gt;]
<br>
<br>Tansport类型包括 HCI USB BCSP H4等，常用的估计就是HCI和BCSP两种。需要注意一下他们的使用场合：
<br>HCI是一个抽象的标准的蓝牙通讯接口，在基于HCI协议调用BCCMD时，需要在Bluez已经建立好hci接口的基础上使用。
<br>BCSP（Bluecore Serial
Protocol）是CSR自己制定的传输层协议，主要目的是用来加强在没有使用CTS、RTS进行流量控制的情况下进行可靠的数据传输的能力。其概念是
相对H3 , H4而言，（ 具体分析，请参考下面杂项一章中相应的小节 ）
<br>
<br>BCCMD的主要用途就是用来读写pskey，这里以 psset 这个command来介绍一下格式：
<br>Psset 格式如下： psset [-r] [-s &lt;stores&gt;] &lt;key&gt; &lt;value&gt;
<br>其它都好理解，关键是-s参数之后跟的store具体的含义。这个参数可以是数值也可以是字符串
<br>查询CSR的BCCMD相关的文档，可以找到具体的含义如下：
<br>
<br>0x0000 Default
<br>0x0008 psram
<br>0x0001 psi
<br>0x0002 psf
<br>0x0004 psrom
<br>0x0003 psi then psf
<br>0x0007 psi, psf then psrom
<br>0x0009 psram then psi
<br>0x000b psram, psi then psf
<br>0x000f psram, psi, psf then psrom
<br>
<br>CSR的蓝牙芯片中，PSKEY可能存储在 rom flash eeprom
ram等介质里，这里的数值指明了psset/get命令操作PSKEY时所针对的存储介质及其优先顺序，通常我们会用 &#8211;s 0x0 或 &#8211;s
&#8220;default&#8221; 来使用该命令，0x0的含义与0xf一样。
<br>
<br>值得注意的是，哪个参数是有效的，还取决于哪一类的存储介质实际存在于蓝牙芯片中，此外，只读类的介质对写操作类的命令也是无效的。
<br>
<br>基本上来说，所修改的都是位于psram中的pskey，此外，pskey修改以后要起作用，还要一并使用 &#8211;r参数，或直接用warmreset命令将蓝牙芯片进行warm reset。
<br>
<br>
<br>7.2	Hciattach
<br>Hciattach主要用来初始化蓝牙设备，它的命令格式如下：
<br>
<br>hciattach [-n] [-p] [-b] [-t timeout] [-s initial_speed] &lt;tty&gt; &lt;type | id&gt; [speed] [flow|noflow] [bdaddr]
<br>
<br>其中最重要的参数就是 type和speed，type决定了要初始化的设备的型号，可以使用 hciattach &#8211;l 来列出所支持的设备型号。
<br>并不是所有的参数对所有的设备都是适用的，有些设备会忽略一些参数设置，例如：查看hciattach的代码就可以看到，多数设备都忽略bdaddr参数。
<br>
<br>Hciattach命令内部的工作步骤是：首先打开制定的tty设备，然后做一些通用的设置，如flow等，然后设置波特率为
initial_speed，然后根据type调用各自的初始化代码，最后将波特率重新设置为speed。所以调用hciattach时，要根据你的实际
情况，设置好initial_speed和speed。
<br>
<br>对于type BCSP来说，它的初始化代码只做了一件事，就是完成BCSP协议的同步操作，它并不对蓝牙芯片做任何的pskey的设置。同步操作的具体流程和规范可以参考CSR的相关文档： BCSP Link Establishment Protocol
<br>
<br>7.3	其它
<br>下面几个，使用了，但是没有太多研究
<br>7.3.1	Hcidump
<br>Hcidump不在bluez-utils包里，而是在单独的hcidump包里。主要用来分析捕获和分析HCI数据包，如果使用bluez过程
中出了什么问题，用hcidump往往可以发现一些出错的线索，原因。 参数很多，基本上hcidump &#8211;X &#8211;V
就可以帮你获得详细的经过格式解析的数据包。
<br>7.3.2	Hcitool
<br>主要用hcitool来scan远端的设备，显示设备地址，名称等。
<br>例如：Hcitool scan， hcitool inq
<br>
<br>7.3.3	Sdptool
<br>主要用来浏览远端设备SDP服务，或者管理本地的SDPD维护的数据库。
<br>常用的应该就是查找远端设备的服务了
<br>例如：
<br>sdptool browse 00:02:72:B0:00:26 浏览地址为00:02:72:B0:00:26的设备所提供的服务
<br>sdptool search 0x1112 00:02:72:B0:00:26 查找地址为00:02:72:B0:00:26的设备上的Headset Audio Gateway服务。
<br>
<br>./sdptool search 0x1112 00:02:72:B0:00:26
<br>Class 0x1112
<br>Inquiring ...
<br>Searching for 0x1112 on 00:02:72:B0:00:26 ...
<br>Service Name: Headset Audio Gateway
<br>Service RecHandle: 0x1001d
<br>Service Class ID List:
<br>  "Headset Audio Gateway" (0x1112)
<br>  "Generic Audio" (0x1203)
<br>。。。
<br>
<br>7.3.4	Hciconfig
<br>这个就不用多说了，格式上很类似于ifconfig，用来设置HCI设备的参数
<br>例如
<br>hciconfig hci0 up 启动hci0接口
<br>hciconfig hci0 iscan 使能位于hci0接口的蓝牙芯片的inquery scan模式（使得设备能被其它蓝牙设备发现）
<br>
<br>
<br>8	杂项
<br>8.1	使用Dbus-send进行测试
<br>由于Bluez使用dbus进行进程间通讯，所以我们可以使用dbus-send命令直接发送命令进行一些查询，试验的工作。
<br>Bluez每个Daemon或service所支持的Dbus接口API描述文本，可以在各自的目录下找到，例如Audio的API写在 audio/audio-api.txt中。
<br>以Audio为例，可以参考 <a  href="http://wiki.bluez.org/wiki/HOWTO/AudioDevices" target="_blank">http://wiki.bluez.org/wiki/HOWTO/AudioDevices</a> 中的描述
<br>
<br>
<br>8.2	HCI、H4、USB、BCSP 之间的关系
<br>个人理解，严格的说HCI和其它几种protocol并不是可以对比的同一层次的东西。
<br>HCI protocol
并不考虑在实际传输载体以及其中的纠错等问题，只是一个抽象的传输层或叫做接口。USB，H3，H4等才是具体的transport
layer（此外还有SD Transport layer）。HCI数据包需要附着在这些具体的Transport Layer的协议包中。
<br>以BCSP为例，4种类型的HCI数据包各自使用了一个BCSP通道，做为这些通道的payload封装在BCSP的协议包里，需要通过TTY
的lldsic层走一次，并由hci_uart模块做相应的封装工作。而BCSP还通过其它通道支持其它的一些自定的Protocol。BCSP作为一个
具体的传输层协议，还支持了校验，同步等功能。
<br>H4机制类似，SD和USB transport好像区别比较大一点。具体可以参考 Bluetooth Specification Volume 4.
<br>
<br>8.3	BCSP数据包结构
<br>HCI数据包的结构，在bluetooth的spec里面有详细定义，不过，CSR自己的BCSP，BCCMD等一系列协议，又添加了一堆的东
西，其中，HCI数据包是作为BCSP的payload，而BCCMD又是作为HCI的payload，所以测试过程中，发觉要分析清楚bluez通过
kernel最后到底往蓝牙芯片的串口发送了什么数据，特别是想要自己手工构建一串数据，着实要看上一堆spec，拼凑起来才能完成。
<br>要具体学习分析一串命令，最好的办法，我能想到的就是修改bccmd的代码，将它传给串口的每一个字符串都打印出来，这样对照这spec看，事半功倍。
<br>
<br>例如下面这条，是使用我修改后的bccmd指令。所做的操作是读取串口波特率的pskey：
<br>
<br>./bccmd.dbg -t bcsp -d /dev/ttyS1 psget -s 0x0 0x01be
<br>
<br>cmd : 00 fc 13 c2 00 00 09 00 01 00 03 70 00 00 be 01 01 00 00 00 00 00
<br>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
<br>
<br>在这里 HCI的数据包是第一行，具体解释一下：
<br>
<br>头4个字节是HCI Head，其中
<br>00 fc ：整体代表这是一个制造商自定义的命令。
<br>13 ：HCI命令长度为0x13。
<br>C2 ：包的内容是唯一的一个BCCMD数据包。
<br>
<br>后面是BCCMD的Head
<br>00 00 ：这是一个GetReq命令
<br>09 00 ：BCCMD的命令9个word长度，及18字节
<br>01 00 ：seqno， 包的顺序标记 包1
<br>03 70 ：varid 7003， 表示这是对PSKEY的操作
<br>00 00 ：状态标志
<br>再下来是BCCMD的payload
<br>be 01 ：0x01be 波特率PSKEY的index
<br>01 00 ：该PSKEY的长度为1
<br>00 00 ：strore 为 00
<br>00 00 ：该PSKEY的值，这里是发送读命令，所以填0
<br>
<br>第二行的数据是将HCI包封装在了BCSP数据包里：
<br>前面部分：c0 d1 65 01 c8 ：
<br>C0 ：是BCSP数据包的分割符
<br>D1 ：类型为可靠链接数据流，有CRC校验
<br>65 01 ：channel 5 （ HCI CMD ）， 长度为0x16
<br>C8 ：包头的校验
<br>后面部分：69 a6 c0：
<br>69 a6 ：整个BCSP包的CRC校验
<br>C0 ：分隔符
<br>
<br>其它命令类似的分析可得。
<br>
<br>如果只是希望看到HCI命令本身，也可以用hcidump来看。这是上面的读pskey操作通过HCI接口操作的dump：
<br>
<br>&lt; HCI Command: Vendor (0x3f|0x0000) plen 19
<br>    BCCMD: Get req: len 9 seqno 1 varid 0x7003 status 0
<br>      PSKEY: key 0x01be len 1 stores 0x0000
<br>        UART_BAUDRATE: value 0 (0x0000)
<br>
<br>8.4	Hid / Serial / HF / OBEX
<br>这几个比较常用的profile，还没测试哪。。。。。。谁给我买个蓝牙鼠标玩玩？！
<br>
<br>8.5	总的遗留问题
<br>整体上，PC上实现的自动识别，自动启动服务的一整套脚本，还没有仔细研究。<img src ="http://www.cnitblog.com/luofuchong/aggbug/56637.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luofuchong/" target="_blank">lfc</a> 2009-04-23 11:57 <a href="http://www.cnitblog.com/luofuchong/archive/2009/04/23/56637.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>alsa交叉编译</title><link>http://www.cnitblog.com/luofuchong/archive/2009/03/15/55437.html</link><dc:creator>lfc</dc:creator><author>lfc</author><pubDate>Sun, 15 Mar 2009 02:11:00 GMT</pubDate><guid>http://www.cnitblog.com/luofuchong/archive/2009/03/15/55437.html</guid><wfw:comment>http://www.cnitblog.com/luofuchong/comments/55437.html</wfw:comment><comments>http://www.cnitblog.com/luofuchong/archive/2009/03/15/55437.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luofuchong/comments/commentRss/55437.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luofuchong/services/trackbacks/55437.html</trackback:ping><description><![CDATA[alsa-lib:<br>./configure --host=arm-linux --prefix=/usr/local/arm/3.4.5/arm-linux --datadir=/usr/share <br>make<br>make install<br><br>alsa-utils:<br>./configure --host=arm-linux --prefix=/home/lfc/work/alsa/target<br>make <br>make install<br><img src ="http://www.cnitblog.com/luofuchong/aggbug/55437.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luofuchong/" target="_blank">lfc</a> 2009-03-15 10:11 <a href="http://www.cnitblog.com/luofuchong/archive/2009/03/15/55437.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ubifs轻松上路</title><link>http://www.cnitblog.com/luofuchong/archive/2009/03/11/55259.html</link><dc:creator>lfc</dc:creator><author>lfc</author><pubDate>Tue, 10 Mar 2009 17:00:00 GMT</pubDate><guid>http://www.cnitblog.com/luofuchong/archive/2009/03/11/55259.html</guid><wfw:comment>http://www.cnitblog.com/luofuchong/comments/55259.html</wfw:comment><comments>http://www.cnitblog.com/luofuchong/archive/2009/03/11/55259.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/luofuchong/comments/commentRss/55259.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luofuchong/services/trackbacks/55259.html</trackback:ping><description><![CDATA[<span style="font-size: 18pt;">第一、什么是ubifs？</span><br><br>由IBM、nokia工程师Thomas Gleixner，Artem Bityutskiy等人于2006年发起，致力于开发性能卓越、扩展性高的FLASH专用文件系统，以解决当前嵌入式环境下以FLASH作为MTD设备使用时的技术瓶颈。<br><br>关键字：<br>UBI：一种类似于LVM的逻辑卷管理层。主要实现损益均衡，逻辑擦除块、卷管理，坏块管理等。<br>UBIFS：基于UBI的FLASH日志文件系统。<br><br>有关ubifs的详细介绍，请参考：<br>http://www.linux-mtd.infradead.org/doc/ubi.html<br>http://www.linux-mtd.infradead.org/doc/ubifs.html<br><br><br><span style="font-size: 18pt;">第二、为何使用ubifs？</span><br><br><br><span style="font-size: 18pt;">第三、如何得到ubifs？</span><br>2.6.22以后，ubifs活跃于git管理工程中：<br>git://git.infradead.org/ubi-2.6.git<br><br>2.6.27以后，ubifs被整合进内核树中，用户只需下载最新内核即可获取ubifs支持。<br><span style="font-size: 24pt;"><span style="font-size: 24pt;"><br><span style="font-size: 18pt;">第四、如何使用ubifs？</span></span><span style="font-size: 18pt;"></span></span><span style="font-size: 18pt;"></span><br>软件环境：<br>linux-2.6.28<br>arm-linux-gcc 3.4.5<br><br>硬件环境：<br>s3c2410<br>k9f1208<br><span style="font-size: 18pt;"><br><span style="font-size: 18pt;">一、准备</span></span><br><br>1、内核<br>配置的时候选上<br>1)Device Drivers&nbsp; ---&gt;Memory Technology Device (MTD) support&nbsp; ---&gt;UBI - Unsorted block images&nbsp; ---&gt;Enable UBI<br>2)File systems&nbsp; ---&gt;Miscellaneous filesystems&nbsp; ---&gt;UBIFS file system support<br><br>2、mtd-utils工具(flash_eraseall、ubiattach、ubimkvol)准备<br>1)下载(mtd-utils、zlib、lzo)源码<br>wget http://debian.mirror.inra.fr/debian/pool/main/m/mtd-utils/mtd-utils_20080508.orig.tar.gz<br>wget http://www.zlib.net/zlib-1.2.3.tar.gz<br>wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.03.tar.gz<br><br>2)编译安装zlib<br>tar xzvf zlib-1.2.3.tar.gz<br>cd zlib-1.2.3<br>CC=arm-linux-gcc ./configure --shared --prefix=/usr/local/arm/3.4.5/arm-linux<br>make<br>make install<br>cd ..<br><br>3)编译安装lzo<br>tar xzvf lzo-2.03.tar.gz<br>cd lzo-2.03<br>CC=arm-linux-gcc ./configure --host=arm-linux --prefix=/usr/local/arm/3.4.5/arm-linux<br>make<br>make install<br>cd ..<br><br>4)编译mtd-utils<br>tar xzvf mtd-utils_20080508.orig.tar.gz<br>cd mtd-utils-20080508<br><br>修改Makefile文件：<br>#CROSS=arm-linux-<br>修改为&nbsp; CROSS=arm-linux-<br>BUILDDIR := $(CROSS:-=)<br>修改为&nbsp; BUILDDIR := .<br><br>修改ubi-utils/Makefile文件：<br>添加&nbsp;&nbsp;&nbsp; CROSS=arm-linux-<br><br>修改&nbsp;&nbsp;&nbsp; ubi-utils/new-utils/Makefile文件：<br>添加&nbsp;&nbsp;&nbsp; CROSS=arm-linux-<br><br>make WITHOUT_XATTR=1<br><br>ubi-utils子目录下生成我们需要的ubiattach、ubimkvol等文件(请确保是交叉编译所得)<br><br>3、mtd-utils工具(mkfs.ubifs、ubinize)准备<br>git-clone git://git.infradead.org/mtd-utils.git<br>cd mtd-utils/<br>make<br><br>mkfs.ubifs子目录下生成我们需要的mkfs.ubifs工具<br>ubi-utils/new-utils子目录下生成我们需要的ubinize工具<br><br><span style="font-size: 18pt;"><br>二、使用</span><br><br>1、使用ramfs或nfs启动系统，执行以下命令挂载ubifs：<br>1)flash_eraseall /dev/mtd4<br>2)ubiattach /dev/ubi_ctrl -m 4<br>3)ubimkvol /dev/ubi0 -N rootfs -s 50MiB<br>4)mount -t ubifs ubi0_0 /mnt或mount -t ubifs ubi0:rootfs /mnt<br><br>2、如果你想使用ubifs为rootfs，把文件系统内容解压到ubifs挂载目录下，并修改内核启动参数为：<br>console=ttySAC0 ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs<br><br>3、如果你想直接在bootloader下烧写ubifs映像，使用以下命令制作ubi烧写映像：<br>mkfs.ubifs -r rootfs -m 512 -e 15872 -c 3303 -o ubifs.img<br>ubinize -o ubi.img -m 512 -p 16KiB -s 256 ubinize.cfg<br><br>其中：<br>1)以上命令的参数可从ubifs挂载信息中提取：<br>UBI: attaching mtd4 to ubi0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>UBI: physical eraseblock size:&nbsp;&nbsp; 16384 bytes (16 KiB)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>UBI: logical eraseblock size:&nbsp;&nbsp;&nbsp; 15872 bytes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>UBI: smallest flash I/O unit:&nbsp;&nbsp;&nbsp; 512&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>UBI: sub-page size:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 256&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>UBI: VID header offset:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 256 (aligned 256)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>UBI: data offset:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 512&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>UBI: attached mtd4 to ubi0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br>2)配置文件ubinize.cfg的内容为：<br>[ubifs]<br>mode=ubi<br>image=ubifs.img<br>vol_id=0<br>vol_size=50MiB<br>vol_type=dynamic<br>vol_name=rootfs<br>vol_flags=autoresize<br><br>注：<br>&nbsp;&nbsp;&nbsp; 其他nand flash下ubifs的使用方法类似(参数不同)。<br><br><br><br><br><br>    <img src ="http://www.cnitblog.com/luofuchong/aggbug/55259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luofuchong/" target="_blank">lfc</a> 2009-03-11 01:00 <a href="http://www.cnitblog.com/luofuchong/archive/2009/03/11/55259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】终端驱动原理篇</title><link>http://www.cnitblog.com/luofuchong/archive/2008/10/07/49936.html</link><dc:creator>lfc</dc:creator><author>lfc</author><pubDate>Tue, 07 Oct 2008 03:50:00 GMT</pubDate><guid>http://www.cnitblog.com/luofuchong/archive/2008/10/07/49936.html</guid><wfw:comment>http://www.cnitblog.com/luofuchong/comments/49936.html</wfw:comment><comments>http://www.cnitblog.com/luofuchong/archive/2008/10/07/49936.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luofuchong/comments/commentRss/49936.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luofuchong/services/trackbacks/49936.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第十四章&nbsp; Linux终端设备驱动本章导读在Linux系统中，终端设备非常重要，没有终端设备，系统将无法向用户反馈信息，Linux中包含控制台、串口和伪终端3类终端设备。 14.1节阐述了终端设备的概念及分类，14.2节给出了Linux终端设备驱动的框架结构，重点描述tty_driver结构体及其成员。14.3~14.5节在14.2节的基础上，分别给出了Linux终端设备驱动模块...&nbsp;&nbsp;<a href='http://www.cnitblog.com/luofuchong/archive/2008/10/07/49936.html'>阅读全文</a><img src ="http://www.cnitblog.com/luofuchong/aggbug/49936.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luofuchong/" target="_blank">lfc</a> 2008-10-07 11:50 <a href="http://www.cnitblog.com/luofuchong/archive/2008/10/07/49936.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>i2c总线使用</title><link>http://www.cnitblog.com/luofuchong/archive/2008/10/05/49882.html</link><dc:creator>lfc</dc:creator><author>lfc</author><pubDate>Sun, 05 Oct 2008 15:44:00 GMT</pubDate><guid>http://www.cnitblog.com/luofuchong/archive/2008/10/05/49882.html</guid><wfw:comment>http://www.cnitblog.com/luofuchong/comments/49882.html</wfw:comment><comments>http://www.cnitblog.com/luofuchong/archive/2008/10/05/49882.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luofuchong/comments/commentRss/49882.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luofuchong/services/trackbacks/49882.html</trackback:ping><description><![CDATA[了解了i2c总线的主要结构成员及适配器、设备驱动的注册后，现在我们从上而下的来研究一下i2c总线的使用(仍然以i2c-dev.c为例)：<br><br>1、这是面向用户的虚拟字符设备所提供的所有i2c总线操作接口函数：<br>static const struct file_operations i2cdev_fops = {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .owner&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = THIS_MODULE,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .llseek&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = no_llseek,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .read&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = i2cdev_read,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .write&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = i2cdev_write,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .ioctl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = i2cdev_ioctl,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .open&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = i2cdev_open,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .release&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = i2cdev_release,<br>};<br><br>1)drivers/i2c/i2c-dev.c<br>static int i2cdev_open(struct inode *inode, struct file *file)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int minor = iminor(inode);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct i2c_client *client;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct i2c_adapter *adap;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct i2c_dev *i2c_dev;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i2c_dev = i2c_dev_get_by_minor(minor);&nbsp;&nbsp;&nbsp; //通过设备文件的从设备号查找对应的i2c_dev<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!i2c_dev)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -ENODEV;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adap = i2c_get_adapter(i2c_dev-&gt;adap-&gt;nr);&nbsp;&nbsp;&nbsp; //查找对于的adap<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!adap)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -ENODEV;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client = kzalloc(sizeof(*client), GFP_KERNEL);&nbsp;&nbsp;&nbsp; //i2c从设备描述结构体<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!client) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i2c_put_adapter(adap);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -ENOMEM;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; snprintf(client-&gt;name, I2C_NAME_SIZE, "i2c-dev %d", adap-&gt;nr);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client-&gt;driver = &amp;i2cdev_driver;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* registered with adapter, passed as client to user */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client-&gt;adapter = adap;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file-&gt;private_data = client;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br>注：<br>&nbsp;&nbsp;&nbsp; i2cdev_open的主要作用是构建并初始化用于描述i2c从设备的结构体struct i2c_client。<br><br>2)drivers/i2c/i2c-dev.c<br>i2cdev_read<br>&nbsp;&nbsp;&nbsp; -&gt; i2c_master_recv<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -&gt; i2c_transfer <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -&gt; adap-&gt;algo-&gt;master_xfer(s3c24xx_i2c_xfer)<br><br>3)drivers/i2c/i2c-dev.c<br>i2cdev_write <br>&nbsp;&nbsp;&nbsp; -&gt; i2c_master_send<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -&gt; i2c_transfer<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -&gt; adap-&gt;algo-&gt;master_xfer(s3c24xx_i2c_xfer)<br><br><br><br>7)drivers/i2c/busses/i2c-s3c2410.c <br>s3c24xx_i2c_xfer <br>&nbsp;&nbsp;&nbsp; -&gt; s3c24xx_i2c_doxfer(wait_event_timeout(i2c-&gt;wait, i2c-&gt;msg_num == 0, HZ * 5)) &lt;----|<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -&gt; s3c24xx_i2c_irq&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -&gt; i2s_s3c_irq_nextbyte&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -&gt; s3c24xx_i2c_stop&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; -&gt; s3c24xx_i2c_master_complete(wake_up(&amp;i2c-&gt;wait))------------------|<br><br><br>    <img src ="http://www.cnitblog.com/luofuchong/aggbug/49882.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luofuchong/" target="_blank">lfc</a> 2008-10-05 23:44 <a href="http://www.cnitblog.com/luofuchong/archive/2008/10/05/49882.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>i2c总线上，适配器、设备驱动注册</title><link>http://www.cnitblog.com/luofuchong/archive/2008/10/05/49881.html</link><dc:creator>lfc</dc:creator><author>lfc</author><pubDate>Sun, 05 Oct 2008 15:43:00 GMT</pubDate><guid>http://www.cnitblog.com/luofuchong/archive/2008/10/05/49881.html</guid><wfw:comment>http://www.cnitblog.com/luofuchong/comments/49881.html</wfw:comment><comments>http://www.cnitblog.com/luofuchong/archive/2008/10/05/49881.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luofuchong/comments/commentRss/49881.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luofuchong/services/trackbacks/49881.html</trackback:ping><description><![CDATA[1、总线适配器注册：<br>1)drivers/i2c/i2c-core.c<br>int i2c_add_adapter(struct i2c_adapter *adapter)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; id, res = 0;<br><br>retry:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (idr_pre_get(&amp;i2c_adapter_idr, GFP_KERNEL) == 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -ENOMEM;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_lock(&amp;core_lists);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* "above" here means "above or equal to", sigh */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res = idr_get_new_above(&amp;i2c_adapter_idr, adapter,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __i2c_first_dynamic_bus_num, &amp;id);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_unlock(&amp;core_lists);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (res &lt; 0) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (res == -EAGAIN)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto retry;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return res;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adapter-&gt;nr = id;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //使用动态的总线号来标识总线适配器。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return i2c_register_adapter(adapter);<br>}<br>EXPORT_SYMBOL(i2c_add_adapter);<br><br>2)drivers/i2c/i2c-core.c<br>static int i2c_register_adapter(struct i2c_adapter *adap)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int res = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct list_head&nbsp;&nbsp; *item;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct i2c_driver&nbsp; *driver;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_init(&amp;adap-&gt;bus_lock);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //初始化总线访问控制变量(总线上数据传输时使用)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_init(&amp;adap-&gt;clist_lock);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //初始化客户端访问控制变量(操作客户端结构时使用)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INIT_LIST_HEAD(&amp;adap-&gt;clients);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //初始化客户端链表头<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_lock(&amp;core_lists);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list_add_tail(&amp;adap-&gt;list, &amp;adapters);&nbsp;&nbsp;&nbsp; //添加到总线适配器链表中<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Add the adapter to the driver core.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * If the parent pointer is not set up,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * we add this adapter to the host bus.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (adap-&gt;dev.parent == NULL) {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adap-&gt;dev.parent = &amp;platform_bus;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pr_debug("I2C adapter driver [%s] forgot to specify "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "physical device\n", adap-&gt;name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(adap-&gt;dev.bus_id, "i2c-%d", adap-&gt;nr);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adap-&gt;dev.release = &amp;i2c_adapter_dev_release;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adap-&gt;dev.class = &amp;i2c_adapter_class;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res = device_register(&amp;adap-&gt;dev);&nbsp;&nbsp;&nbsp; //注册设备<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (res)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto out_list;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dev_dbg(&amp;adap-&gt;dev, "adapter [%s] registered\n", adap-&gt;name);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* create pre-declared device nodes for new-style drivers */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (adap-&gt;nr &lt; __i2c_first_dynamic_bus_num)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i2c_scan_static_board_info(adap);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* let legacy drivers scan this bus for matching devices */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list_for_each(item,&amp;drivers) {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //搜索总线上的所有设备驱动，通过调用其attach_adapter接口函数，查找匹配的设备。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driver = list_entry(item, struct i2c_driver, list);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (driver-&gt;attach_adapter)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* We ignore the return code; if it fails, too bad */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driver-&gt;attach_adapter(adap);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>out_unlock:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_unlock(&amp;core_lists);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return res;<br><br>out_list:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list_del(&amp;adap-&gt;list);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; idr_remove(&amp;i2c_adapter_idr, adap-&gt;nr);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto out_unlock;<br>}<br><br>2、设备驱动注册(以i2c-dev.c为例)：<br>1)include/linux/i2c.h<br>static inline int i2c_add_driver(struct i2c_driver *driver)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return i2c_register_driver(THIS_MODULE, driver);<br>}<br><br>2)drivers/i2c/i2c-core.c<br>int i2c_register_driver(struct module *owner, struct i2c_driver *driver)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int res;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* new style driver methods can't mix with legacy ones */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (is_newstyle_driver(driver)) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (driver-&gt;attach_adapter || driver-&gt;detach_adapter<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; || driver-&gt;detach_client) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printk(KERN_WARNING<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "i2c-core: driver [%s] is confused\n",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driver-&gt;driver.name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -EINVAL;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* add the driver to the list of i2c drivers in the driver core */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driver-&gt;driver.owner = owner;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driver-&gt;driver.bus = &amp;i2c_bus_type;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* for new style drivers, when registration returns the driver core<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * will have called probe() for all matching-but-unbound devices.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res = driver_register(&amp;driver-&gt;driver);&nbsp;&nbsp;&nbsp; //注册驱动<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (res)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return res;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_lock(&amp;core_lists);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list_add_tail(&amp;driver-&gt;list,&amp;drivers);&nbsp;&nbsp;&nbsp; //添加到设备驱动链表中<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pr_debug("i2c-core: driver [%s] registered\n", driver-&gt;driver.name);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* legacy drivers scan i2c busses directly */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (driver-&gt;attach_adapter) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct i2c_adapter *adapter;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list_for_each_entry(adapter, &amp;adapters, list) {&nbsp;&nbsp;&nbsp; //让设备驱动搜索匹配的适配器(通过调用其attach_adapter接口)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driver-&gt;attach_adapter(adapter);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_unlock(&amp;core_lists);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>}<br>EXPORT_SYMBOL(i2c_register_driver);<br><br>3)drivers/i2c/i2c-dev.c<br>static int i2cdev_attach_adapter(struct i2c_adapter *adap)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct i2c_dev *i2c_dev;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int res;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i2c_dev = get_free_i2c_dev(adap);&nbsp;&nbsp;&nbsp; //创建并初始化i2c_dev结构<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (IS_ERR(i2c_dev))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return PTR_ERR(i2c_dev);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* register this i2c device with the driver core */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i2c_dev-&gt;dev = device_create(i2c_dev_class, &amp;adap-&gt;dev,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //注意，这里使用的次设备号为adap-&gt;nr，便于以后获取adap结构。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MKDEV(I2C_MAJOR, adap-&gt;nr),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "i2c-%d", adap-&gt;nr);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (IS_ERR(i2c_dev-&gt;dev)) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res = PTR_ERR(i2c_dev-&gt;dev);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto error;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res = device_create_file(i2c_dev-&gt;dev, &amp;dev_attr_name);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //创建设备文件<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (res)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto error_destroy;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adap-&gt;name, adap-&gt;nr);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>error_destroy:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap-&gt;nr));<br>error:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return_i2c_dev(i2c_dev);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return res;<br>}<br><br>总结：<br>&nbsp;&nbsp;&nbsp; 一个适配器对应一个i2c控制器。<br><br><br><img src ="http://www.cnitblog.com/luofuchong/aggbug/49881.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luofuchong/" target="_blank">lfc</a> 2008-10-05 23:43 <a href="http://www.cnitblog.com/luofuchong/archive/2008/10/05/49881.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>i2c关键结构体分析</title><link>http://www.cnitblog.com/luofuchong/archive/2008/09/15/49114.html</link><dc:creator>lfc</dc:creator><author>lfc</author><pubDate>Mon, 15 Sep 2008 15:38:00 GMT</pubDate><guid>http://www.cnitblog.com/luofuchong/archive/2008/09/15/49114.html</guid><wfw:comment>http://www.cnitblog.com/luofuchong/comments/49114.html</wfw:comment><comments>http://www.cnitblog.com/luofuchong/archive/2008/09/15/49114.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luofuchong/comments/commentRss/49114.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luofuchong/services/trackbacks/49114.html</trackback:ping><description><![CDATA[1、总线配置结构体：<br>struct s3c2410_platform_i2c {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int&nbsp;&nbsp;&nbsp; flags;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int&nbsp;&nbsp;&nbsp; slave_addr;&nbsp;&nbsp;&nbsp;&nbsp; /* slave address for controller */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long&nbsp;&nbsp; bus_freq;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* standard bus frequency */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long&nbsp;&nbsp; max_freq;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* max frequency for the bus */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long&nbsp;&nbsp; min_freq;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* min frequency for the bus */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int&nbsp;&nbsp;&nbsp; sda_delay;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* pclks (s3c2440 only) */<br>};<br><br>2、总线描述结构体：<br>struct s3c24xx_i2c {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spinlock_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lock;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//自选锁(防止总线资源被并发访问)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait_queue_head_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//等待队列(当有数据需要收/发时启动总线，然后守候在等待队列，直到数据收/发结束后被唤醒返回)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct i2c_msg&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *msg;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//i2c信息指针<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg_num;&nbsp;&nbsp; &nbsp;//需要传输的i2c msg数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg_idx;&nbsp;&nbsp; &nbsp;//成功传输的i2c msg数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg_ptr;&nbsp;&nbsp; &nbsp;//当前i2c msg内指针<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tx_setup;&nbsp;&nbsp; &nbsp;//延时值(保证总线启动时数据已经传输到总线上)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum s3c24xx_i2c_state&nbsp; state;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//i2c总线状态<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void __iomem&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *regs;：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct clk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *clk;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct device&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *dev;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct resource&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *irq;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct resource&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *ioarea;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct i2c_adapter&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adap;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//总线适配器(个人觉得它更像设备驱动中的设备而非驱动)<br>};<br><br>3、总线适配器：<br>struct i2c_adapter {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct module *owner;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int id;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int class;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const struct i2c_algorithm *algo; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//i2c总线访问算法<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *algo_data;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//用来保存struct s3c24xx_i2c结构指针<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* --- administration stuff. */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*client_register)(struct i2c_client *);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*client_unregister)(struct i2c_client *);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* data fields that are valid for all devices&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u8 level;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//nesting level for lockdep<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct mutex bus_lock;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct mutex clist_lock;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int timeout;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int retries;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct device dev;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//the adapter device<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int nr;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct list_head clients;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct list_head list;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char name[48];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct completion dev_released;<br>};<br><br>4、总线访问算法：<br>struct i2c_algorithm {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* If an adapter algorithm can't do I2C-level access, set master_xfer<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; to NULL. If an adapter algorithm can do SMBus access, set<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; smbus_xfer. If set to NULL, the SMBus protocol is simulated<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using common I2C messages */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* master_xfer should return the number of messages successfully<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; processed, or a negative value on error */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs,&nbsp;&nbsp; &nbsp;//i2c msg发送函数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int num);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned short flags, char read_write,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u8 command, int size, union i2c_smbus_data * data);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* --- ioctl like call to set div. parameters. */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* To determine what the adapter supports */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u32 (*functionality) (struct i2c_adapter *);&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//标志i2c适配器所支持的功能<br>};<br><br>struct i2c_msg {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __u16 addr;&nbsp;&nbsp;&nbsp;&nbsp; /* slave address&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __u16 flags;<br>#define I2C_M_TEN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x10&nbsp;&nbsp;&nbsp; /* we have a ten bit chip address&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>#define I2C_M_RD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x01<br>#define I2C_M_NOSTART&nbsp;&nbsp; 0x4000<br>#define I2C_M_REV_DIR_ADDR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x2000<br>#define I2C_M_IGNORE_NAK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x1000<br>#define I2C_M_NO_RD_ACK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x0800<br>#define I2C_M_RECV_LEN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x0400 /* length will be first received byte */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __u16 len;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* msg length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __u8 *buf;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* pointer to msg data&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>};<br><br>这里有我画的简单i2c重要结构体分析图：<br>http://www.cnitblog.com/Files/luofuchong/i2c%E9%87%8D%E8%A6%81%E7%BB%93%E6%9E%84%E4%BD%93.rar<br> <img src ="http://www.cnitblog.com/luofuchong/aggbug/49114.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luofuchong/" target="_blank">lfc</a> 2008-09-15 23:38 <a href="http://www.cnitblog.com/luofuchong/archive/2008/09/15/49114.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：Linux I2C 驱动分析</title><link>http://www.cnitblog.com/luofuchong/archive/2008/08/23/48280.html</link><dc:creator>lfc</dc:creator><author>lfc</author><pubDate>Sat, 23 Aug 2008 03:01:00 GMT</pubDate><guid>http://www.cnitblog.com/luofuchong/archive/2008/08/23/48280.html</guid><wfw:comment>http://www.cnitblog.com/luofuchong/comments/48280.html</wfw:comment><comments>http://www.cnitblog.com/luofuchong/archive/2008/08/23/48280.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/luofuchong/comments/commentRss/48280.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luofuchong/services/trackbacks/48280.html</trackback:ping><description><![CDATA[最近在看Linux 2.6.21内核的I2C驱动，也在网上查了一下资料，有错也有对，有些心得，记录下来吧。里面认识或许多有不当之处，还恳请指正。
<div>&nbsp;</div>
<div>1. I2C 协议</div>
<div><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US"><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US"><span></span></span></v:shapetype></span>&nbsp;</div>
<div><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US"><v:shapetype coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US"><span>&nbsp;</span>1.1&nbsp; I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">总线工作原理</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: Verdana;"> </span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;" lang="EN-US"><o:p></o:p></span></v:shapetype></span></div>
<div><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv></span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">总线是由数据线</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">SDA</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">和时钟</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">SCL</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">构成的串行总线，各种被控制器件均并联在这条总线上，每个器件都有一个唯一的地址识别，可以作为总线上的一个发送器件或接收器件</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">(</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">具体由器件的功能决定</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">)</span></div>
<div><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">1.2&nbsp; I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv></span><font face="宋体"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;">总线的几种信号状态</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US"><o:p></o:p></span></font></span></div>
<div>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.&nbsp; </span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">空闲状态：</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">SDA</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">和</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">SCL</span><font face="宋体"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;">都为高电平。</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US"><o:p></o:p></span></font></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.&nbsp; </span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">开始条件</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">(S)</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">：</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">SCL</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">为高电平时，</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">SDA</span><font face="宋体"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;">由高电平向低电平跳变，开始传送数据。</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US"><o:p></o:p></span></font></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.&nbsp; </span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">结束条件</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">(P)</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">：</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">SCL</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">为低电平时，</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">SDA</span><font face="宋体"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;">由低电平向高电平跳变，结束传送数据。</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US"><o:p></o:p></span></font></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.&nbsp; </span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">数据有效：在</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">SCL</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">的高电平期间，</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US"> SDA</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">保持稳定，数据有效。</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">SDA</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">的改变只能发生在</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">SCL</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">的底电平期间。</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: Verdana;">&nbsp;</span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">5.&nbsp; ACK</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">信号</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">: </span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">数据传输的过程中，接收器件每接收一个字节数据要产生一个</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">ACK</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">信号，向发送器件发出特定的低电平脉冲，表示已经收到数据。</font></span></p>
<span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;">
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">1.3&nbsp; I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">总线基本操作</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: Verdana;"> <span lang="EN-US"><o:p></o:p></span></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><font face="宋体">总线必须由主器件（通常为微控制器）控制，主器件产生串行时钟（</font></span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US">SCL</span><font face="宋体"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;">），同时控制总线的传输方向，并产生开始和停止条件。</span><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%; font-family: verdana;" lang="EN-US"><o:p></o:p></span></font></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">数据传输中，首先主器件产生开始条件，随后是器件的控制字节（前七位是从器件的地址，最后一位为读写位</span><span style="font-size: 9pt; color: #3b3b3b; font-family: Verdana;"> </span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">）。接下来是读写操作的数据，以及</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US"> ACK</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">响应信号。数据传输结束时，主器件产生停止条件</span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"></span>&nbsp;</p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><strong>2. Linux I2C 结构分析</strong></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">2.1 层次分析</span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">1. I2C Core</span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">&nbsp;I2C Core<font size="2">用于维护Linux的I2C核心部分，<span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">其中维护了两个静态的</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">List</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">，分别记录系统中的</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv> driver</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">结构和</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv> adapter</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">结构。</span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"></span></font></span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font style="background-color: #c7c7c7;" size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">static LIST_HEAD(adapters);</span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font style="background-color: #c7c7c7;">static LIST_HEAD(drivers);</font></span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv> core</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">提供接口函数，允许一个</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv> adatper</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">，</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv> driver</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">和</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv> client</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">初始化时在</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv> core</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">中进行注册，以及退出时进行注销。具体可以参见i2c_core.c代码。</span></span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">同时还提供了</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv></span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">总线读写访问的一般接口（具体的实现在与</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv></span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">控制器相关的</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv> adapter</span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">中实现），主要应用在</span><span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv></span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">设备驱动中。</span></span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">常用的主要是</span></span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font style="background-color: #c7c7c7;" size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">i2c_master_send()</span></span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font style="background-color: #c7c7c7;" size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">i2c_master_recv()</span></span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font style="background-color: #c7c7c7;" size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">i2c_transfer()</span></span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font style="background-color: #c7c7c7;" size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"></span></span></font></span>&nbsp;</p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">2. I2C&nbsp;bus driver</span></span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: black; font-family: 宋体;">总线驱动的职责，是为系统中每个</span><span style="font-size: 9pt; color: black; font-family: ˎ̥;" lang="EN-US"><font face="宋体, MS Song">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv></font></span><span style="font-size: 9pt; color: black; font-family: 宋体;">总线增加相应的读写方法。但是总线驱动本身并不会进行任何的通讯，它只是存在在那里，等待设备驱动调用其函数。</span></span></span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: black; font-family: 宋体;"></span></span></span></font></span><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: black; font-family: 宋体;"><span style="font-size: 9pt; color: black; line-height: 150%; font-family: 宋体;">在系统开机时，首先装载的是</span><span style="font-size: 9pt; color: black; line-height: 150%; font-family: ˎ̥;" lang="EN-US"><font face="Times New Roman">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv></font></span><span style="font-size: 9pt; color: black; line-height: 150%; font-family: 宋体;">总线驱动。一个总线驱动用于支持一条特定的</span><span style="font-size: 9pt; color: black; line-height: 150%; font-family: ˎ̥;" lang="EN-US"><font face="Times New Roman">I<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2C</st1:chmetcnv></font></span><span style="font-size: 9pt; color: black; line-height: 150%; font-family: 宋体;">总线的读写。一个总线驱动通常需要两个模块，一个</span><span style="font-size: 9pt; color: black; line-height: 150%; font-family: ˎ̥;" lang="EN-US"><font face="Times New Roman">struct i<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2c</st1:chmetcnv>_adapter</font></span><span style="font-size: 9pt; color: black; line-height: 150%; font-family: 宋体;">和一个</span><span style="font-size: 9pt; color: black; line-height: 150%; font-family: ˎ̥;" lang="EN-US"><font face="Times New Roman">struct i<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2c</st1:chmetcnv>_algorithm</font></span><span style="font-size: 9pt; color: black; line-height: 150%; font-family: 宋体;">来描述：</span><span style="font-size: 9pt; color: black; line-height: 150%; font-family: ˎ̥;" lang="EN-US"><font face="Times New Roman"> </font></span></span></span></span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: black; font-family: 宋体;"><span style="font-size: 9pt; color: black; line-height: 150%; font-family: ˎ̥;" lang="EN-US"><font face="Times New Roman">在
buses目录下的i2c-pxa.c中实现了PXA的I2C总线适配器，I2C adapter 构造一个对I2C
core层接口的数据结构，并通过接口函数向I2C core注册一个控制器。I2C
adapter主要实现对I2C总线访问的算法，iic_xfer() 函数就是I2C adapter底层对I2C总线读写方法的实现。同时I2C
adpter 中还实现了对I2C控制器中断的处理函数。 <br></font></span></span></span></span></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: black; font-family: 宋体;"><span style="font-size: 9pt; color: black; line-height: 150%; font-family: ˎ̥;" lang="EN-US"><font face="Times New Roman">1) i2c-pxa.c定义了i2c_algorithm，并且实现了master的发送函数i2c_pxa_xfer()，以及设备查询总线的模式的函数i2c_pxa_functionality()</font></span></span></span></span></font></span></p>
</span>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 24pt; line-height: 150%; text-align: left;" align="left"><span style="font-size: 9pt; color: black; line-height: 150%; font-family: ˎ̥;" lang="EN-US"><font size="2"><font face="Times New Roman"><o:p>
<table style="border: 1px solid #999999; font-size: 12px; width: 80%;" align="center">
    <tbody>
        <tr>
            <td>static const struct i2c_algorithm i2c_pxa_algorithm = {<br>&nbsp;.master_xfer&nbsp;= i2c_pxa_xfer,<br>&nbsp;.functionality&nbsp;= i2c_pxa_functionality,<br>};</td>
        </tr>
    </tbody>
</table>
</o:p></font></font></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2">2) i2c-pxa.c中，实现了i2c_adapter，主要是在定义pxa-i2c时进行初始化，并且i2c_pxa_probe()中进行填充parent指针，并且调用</font></span></span></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2">ret = i2c_add_adapter(&amp;i2c-&gt;adap);</font></span></span></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2">进行添加。 </font></span></span></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">
<table style="border: 1px solid #999999; font-size: 12px; width: 80%;" align="center">
    <tbody>
        <tr>
            <td>static struct pxa_i2c i2c_pxa = {<br>&nbsp;.lock&nbsp;= SPIN_LOCK_UNLOCKED,<br>&nbsp;.adap&nbsp;= {<br>&nbsp;&nbsp;.owner&nbsp;&nbsp;= THIS_MODULE,<br>&nbsp;&nbsp;.algo&nbsp;&nbsp;= &amp;i2c_pxa_algorithm,<br>&nbsp;&nbsp;.name&nbsp;&nbsp;= "pxa2xx-i2c.0",<br>&nbsp;&nbsp;.retries&nbsp;= 5,<br>&nbsp;},<br>};</td>
        </tr>
    </tbody>
</table>
</span></span></span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;">总的来说，在i2c-pxa中，使用platform驱动模型，完成了i2c的总线两种模块<span style="font-size: 9pt; color: black; font-family: ˎ̥;" lang="EN-US"><font face="宋体, MS Song">struct i<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2c</st1:chmetcnv>_adapter</font></span><span style="font-size: 9pt; color: black; font-family: 宋体;">和</span><span style="font-size: 9pt; color: black; font-family: ˎ̥;" lang="EN-US"><font face="宋体, MS Song">struct i<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2c</st1:chmetcnv>_algorithm</font></span></span></font></span></p>
<span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: black; font-family: ˎ̥;" lang="EN-US"></span></span></font></span></div>
<span style="font-size: 9pt; color: #3b3b3b; font-family: verdana;" lang="EN-US"><span style="font-size: 9pt; color: #3b3b3b; line-height: 200%;"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><font size="2"><span style="font-size: 9pt; color: #3b3b3b; font-family: 宋体;"><span style="font-size: 9pt; color: black; font-family: ˎ̥;" lang="EN-US"></span>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;">&nbsp;</p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;">3. I2C device driver</p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;">I2C只有总线驱动是不够的，必须有设备才能工作。这就是I2C device driver的必要性。I2C的device是有<span style="font-size: 9pt; color: black; font-family: 宋体;">两个模块来描述的，</span><span style="font-size: 9pt; color: black; font-family: ˎ̥;" lang="EN-US"><font face="宋体, MS Song">struct i<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2c</st1:chmetcnv>_driver</font></span><span style="font-size: 9pt; color: black; font-family: 宋体;">和</span><span style="font-size: 9pt; color: black; font-family: ˎ̥;" lang="EN-US"><font face="宋体, MS Song">struct i<st1:chmetcnv unitname="C" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2c</st1:chmetcnv>_client</font></span><span style="font-size: 9pt; color: black; font-family: 宋体;">。</span></p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;">在介绍chips目录下的device driver前有必要介绍一下i2c-dev.c文件。</p>
<p><font face="Verdana">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font>i2c-dev.c中提供了一个通用的I2C设备的驱动程序，实现了字符类
型设备的访问接口，对设备的具体访问是通过I2C adapter来实现的。构造一个对I2C core层接口的数据结构，通过接口函数向 I2C
Core注册一个I2C设备驱动。同时构造一个对用户层接口的数据结构，并通过接口函数向内核注册为一个主设备号为89的字符类型设备。</p>
<p>
<table style="border: 1px solid #999999; font-size: 12px; width: 80%;" align="center">
    <tbody>
        <tr>
            <td>
            <p>static struct i2c_driver i2cdev_driver = {<br>&nbsp;.driver = {<br>&nbsp;&nbsp;.name&nbsp;= "dev_driver",<br>&nbsp;},<br>&nbsp;.id&nbsp;&nbsp;= I2C_DRIVERID_I2CDEV,<br>&nbsp;.attach_adapter&nbsp;= i2cdev_attach_adapter,<br>&nbsp;.detach_adapter&nbsp;= i2cdev_detach_adapter,<br>&nbsp;.detach_client&nbsp;= i2cdev_detach_client,<br>};</p>
            <p>struct i2c_dev {<br>&nbsp;struct list_head list;<br>&nbsp;struct i2c_adapter *adap;<br>&nbsp;struct device *dev;<br>};</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;">该
文件提供了用户层对I2C设备的访问，包括open，read，write，ioctl，release等常规文件操作，我们可以通过open函数打开
I2C的设备文件，通过ioctl函数设定要访问从设备的地址，然后就可以通过 read和write函数完成对I2C设备的读写操作。</p>
<p style="margin: 0cm 0cm 0pt; line-height: 200%; text-align: justify;">
<table style="border: 1px solid #999999; font-size: 12px; width: 80%;" align="center">
    <tbody>
        <tr>
            <td>static const struct file_operations i2cdev_fops = {<br>&nbsp;.owner&nbsp;&nbsp;= THIS_MODULE,<br>&nbsp;.llseek&nbsp;&nbsp;= no_llseek,<br>&nbsp;.read&nbsp;&nbsp;= i2cdev_read,<br>&nbsp;.write&nbsp;&nbsp;= i2cdev_write,<br>&nbsp;.ioctl&nbsp;&nbsp;= i2cdev_ioctl,<br>&nbsp;.open&nbsp;&nbsp;= i2cdev_open,<br>&nbsp;.release&nbsp;= i2cdev_release,<br>};</td>
        </tr>
    </tbody>
</table>
</p>
<p><font face="Verdana">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注：</font>通过I2C
driver提供的通用方法可以访问任何一个I2C的设备，但是其中实现的read，write及ioctl等功能完全是基于一般设备的实现，所有的操作
数据都是基于字节流，没有明确的格式和意义。为了更方便和有效地使用I2C设备，我们可以为一个具体的I2C设备开发特定的I2C设备驱动程序，在驱动中
完成对特定的数据格式的解释以及实现一些专用的功能。</p>
<p>在chips目录下包含着各种device 的driver，完成各种从设备的注册。作为一般的I2C设备，使用i2c-dev.c里的操作足够完成操作了。</p>
<p>当然如果不能完成，则需要独立完成该驱动，这就是chips目录下的代码。
因为i2c-dev.c已经实现了I2C设备的文件操作接口，所以只要实现struct
i2c_driver就可以了。对于某些特殊的操作，可以使用command接口进行控制。 当然，对于i2接口的fm芯片，则将struct
i2c_driver放在i2c的chips目录下，而将另外fm操作相关的代码放在了/media/radio目录下了。在这个目录下需要完成读写接口
的完成，这个大部分使用V4L2架构。</p>
<p>继续分析中&#8230;&#8230;</p>
</span></font></span></span></span><img src ="http://www.cnitblog.com/luofuchong/aggbug/48280.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luofuchong/" target="_blank">lfc</a> 2008-08-23 11:01 <a href="http://www.cnitblog.com/luofuchong/archive/2008/08/23/48280.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>