sa

 
linux2.6内核中的sys文件系统
一. sys文件系统简介
sys文件系统是指/sys目录、以及其下面的子目录及其中的文件。它是一个虚拟文件系统,它是内核中各个设备
模块的一个映象(英文称为 kobject),用于将系统中的设备组织成层次结构,每当内核加载一个设备就会在sysfs中
生成相应的目录结构,里面展示出这个设备的状态,控制接口、系统中断等信息。/sys目录是sysfs文件系统挂载点,
当我们把它挂载到 /sys目录中后,我们就有了一个与这些设备打交道的用户层面的接口。我们可以通过它来了解设
备的使用状况,对其进行调整。sys文件系统的背后是Linux设备驱动模型的支持。每个sys文件系统子目录都对应着
一个 kobject。sys文件系统中的文件又被称为属性,为我们察看内核里的设备和驱动打开了一扇方便的窗口。很好
地理解并利用sys文件系统,可以帮助我们加快学习Linux device driver程序设计的进程,同时,在将来调试、
诊断、改进程序设计方面都会起到非常大的作用。
 
sys文件系统主要包括bus子目录,devices子目录,class子目录, 和module子目录等。这些子目录是相互联系的,
你会看到很多他们之间的目录链接。
1. /sys/block/ :包含所有的块设备
2. /sys/bus/ :包含系统中所有的总线类型
3. /sys/class/ :系统中的设备类型(如网卡设备,声卡设备等)
4. /sys/devices/ :包含系统所有的设备,并根据设备挂接的总线类型组织成层次结构
5. /sys/firmware/
6. /sys/fs/
7. /sys/kernel/
8. /sys/module/
9. /sys/power/
Drivers目录:包括内核中所有已注册的设备驱动程序
 
二. sys文件系统和proc文件系统的比较
/sys和/proc都是内核导向用户空间的一个窗口,都是虚拟的文件系统, 可以在内核中由函数接口来创建。虽然
这两种文件系统都是存在于系统内存中,但sys文件系统是device driver提供给用户模式下应用程序的接口,应用程
序通过sys文件系统的文件服务,可以监视,控制设备驱动程序的运行;而proc文件系统是 Linux kernel提供给用户
模式下应用程序的接口,应用程序通过proc文件系统的文件服务,可以监视,控制设备内核程序的运行。
 
 
2、Linux设备驱动模型是与sysfs紧密相关的
Kobject 是Linux 2.6引入的新的设备管理机制,在内核中由struct kobject表示。通过这个数据结构使所有设备
在底层都具有统一的接口,kobject提供基本的对象管理,是构成Linux 2.6设备模型的核心结构,它与sysfs文件系
统紧密关联,每个在内核中注册的kobject对象都对应于sysfs文件系统中的一个目录。
Kobject结构定义为:
struct kobject {
char * k_name; 指向设备名称的指针
char name[KOBJ_NAME_LEN]; 设备名称
struct kref kref;对象引用计数
struct list_head entry; 挂接到所在kset中去的单元
struct kobject * parent; 指向父对象的指针
struct kset * kset; 所属kset的指针
struct kobj_type * ktype; 指向其对象类型描述符的指针
struct dentry * dentry; sysfs文件系统中与该对象对应的文件节点路径指针
};
2.2 kset内核对象集合
Kobject通常通过kset组织成层次化的结构,kset是具有相同类型的kobject的集合,在内核中用kset数据结构表示,
定义为:
struct kset {
struct subsystem * subsys; 所在的subsystem的指针
struct kobj_type * ktype; 指向该kset对象类型描述符的指针
struct list_head list; 用于连接该kset中所有kobject的链表头
struct kobject kobj; 嵌入的kobject
struct kset_hotplug_ops * hotplug_ops; 指向热插拔操作表的指针
};
 
包 含在kset中的所有kobject被组织成一个双向循环链表,list域正是该链表的头。Ktype域指向一个kobj_type结构,
被该 kset中的所有kobject共享,表示这些对象的类型。Kset数据结构还内嵌了一个kobject对象(由kobj域表示),所
有属于这个kset 的kobject对象的parent域均指向这个内嵌的对象。此外,kset还依赖于kobj维护引用计数:kset的
引用计数实际上就是内嵌的 kobject对象的引用计数。
 
 
使一个 kobject 在 sysfs 出现仅仅是调用 kobject_add 的事情. 我们已经见到这个函数作为添加一个 kobject 到一个 kset 的方式; 在 sysfs 中创建入口也是它的工作的一部分. 有一些事情值得知道, 关于 sysfs 入口如何创建:
 
1.kobjects 的 sysfs 入口一直为目录, 因此一个对 kobject_add 的调用导致在sysfs 中创建一个目录. 常常地, 这个目录包含一个或多个属性; 我们稍后见到属性如何指定.
 
2.分配给 kobject 的名字( 用 kobject_set_name ) 是给 sysfs 目录使用的名字. 因此, 出现在 sysfs 层次的相同部分的 kobjects 必须有独特的名字. 分配给 kobjects 的名字也应当是合理的文件名字: 它们不能包含斜线字符, 并且空白的使用强烈不推荐.
 
3.sysfs 入口位于对应 kobject 的 parent 指针的目录中. 如果 parent 是 NULL 当 kobject_add 被调用时, 它被设置为嵌在新 kobject 的 kset 中的 kobject; 因此, sysfs 层级常常匹配使用 kset 创建的内部层次. 如果 parent 和 kset 都是 NULL, sysfs 目录在顶级被创建, 这几乎当然不是你所要的.
 
含几个结构和结构对于的操作。主要如下:
1.super_block(超级块对象) 和对于的操作super_operations
2.inode(索引节点对象)和对应的操作inode_operations,该结构了包含了驱动程序用到的主设备号和次设备号,以及对于设备指针。
3.dentry(目录项对象)和dentry_operations,这个结构在写驱动时基本上没有涉及。
4.file(文件对象)和file_operations,相信这个我们大家都非常熟悉,写驱动的主要工作就是使用该文件对象对应的操作,在2.4版本基本就是这样。
另外还有一个结构就是cdev
有关代码就主要其中在fs目录下。可以去看看,但是不要走的太远,有个了解就可以了。
 
接下来就要分析设备驱动模型了,其实就是几个结构和将这连在一起的操作。主要有一下结构:
1.bus_type,描述总线的结构
2.class,设备分类结构,就是将属于某种类型的设备在一起管理,像所有的各种输入设备,就被统一规划为输入类。
3.device,具体或者虚拟的设备描述结构
4.device_driver,对于的设备驱动程序结构
该部分代码主要在drvier/base下面。
 
为了方面管理这些结构,又产生几个新的结构
1.kobject
2.kset,该结构为kobject一个集合,描述一类设备。
这两个结构的主要代码在lib中。
 
 
 
每当内核加载一个设备就会在sysfs中生成相应的目录结构,为了维护这一系列的属性,内核中提供了一系列的函数:
sysfs_create_dir
sysfs_create_group
sysfs_create_link
sysfs_create_group
sysfs_remove_file
sysfs_remove_link
sysfs_remove_group
sysfs_chmod_file
sysfs_create_bin_file
 
 
 
fs/dcache.c:39:EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure);
fs/sysfs/bin.c:278:EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
fs/sysfs/bin.c:279:EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
fs/sysfs/dir.c:638:EXPORT_SYMBOL_GPL(sysfs_get_dirent);
fs/sysfs/file.c:470:EXPORT_SYMBOL_GPL(sysfs_notify_dirent);
fs/sysfs/file.c:487:EXPORT_SYMBOL_GPL(sysfs_notify);
fs/sysfs/file.c:569:EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
fs/sysfs/file.c:622:EXPORT_SYMBOL_GPL(sysfs_chmod_file);
fs/sysfs/file.c:659:EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
fs/sysfs/file.c:721:EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
fs/sysfs/file.c:724:EXPORT_SYMBOL_GPL(sysfs_create_file);
fs/sysfs/file.c:725:EXPORT_SYMBOL_GPL(sysfs_remove_file);
fs/sysfs/group.c:152:EXPORT_SYMBOL_GPL(sysfs_create_group);
fs/sysfs/group.c:153:EXPORT_SYMBOL_GPL(sysfs_update_group);
fs/sysfs/group.c:154:EXPORT_SYMBOL_GPL(sysfs_remove_group);
fs/sysfs/symlink.c:215:EXPORT_SYMBOL_GPL(sysfs_create_link);
fs/sysfs/symlink.c:216:EXPORT_SYMBOL_GPL(sysfs_remove_link);
fs/sysfs/mount.c:125:EXPORT_SYMBOL_GPL(sysfs_get);
fs/sysfs/mount.c:132:EXPORT_SYMBOL_GPL(sysfs_put);
fs/inode.c:1118:EXPORT_SYMBOL_GPL(generic_drop_inode);
 
驱动开发基础文章:
================
usb驱动
Linux设备模型之tty驱动架构分析
armlinux lcd驱动分析2
http://laocainiao.spaces.eepw.com.cn/articles/article/item/19419
Linux设备驱动之I2C架构分析
i2s cs42l51 驱动分析
http://blog.csdn.net/yinkaizhong/archive/2009/05/19/4202212.aspx
i2c_probe()及I2C设备地址
http://linux.chinaunix.net/bbs/thread-1059290-1-1.html
RTC设备驱动
http://blog.chinaunix.net/u1/38038/showart_686041.html
writing-client-i2c.txt
http://searchjob.ctocio.com.cn/thread-7847309-1-1.html
Linux设备驱动之I2C架构分析
http://bbs.tech.ccidnet.com/simple/index.php?t649517.html
用ALSA驱动声卡流程详解
http://www.linuxsir.org/bbs/thread217259.html
声卡驱动ALSA安装指南(第二版)
http://www.itus.cn/os/3/Linux-21187.shtml
Linux设备驱动程序学习(13)-Linux设备模型(总线、设备、驱动程序和类)
http://blog.chinaunix.net/u2/62910/showart_493458.html
 
I2C设备与驱动的关联
浅析linux 2.6.23 bus总线模型下match()和probe()函数调用顺序
http://idcnews.net/html/edu/20070101/286037.html
linux设备模型深探
http://blog.chinaunix.net/u1/51562/showart_1077877.html
linux引导分析
http://blog.chinaunix.net/u1/51562/showart_1018436.html
浅析linux 2.6.23驱动自动匹配设备driver_attach()函数
http://bbs.cnttr.com/archiver/tid-134480.html
platform_device和platform_driver(一)
http://blog.csdn.net/unbutun/archive/2009/03/26/4026474.aspx
platform_device和platform_driver(二)
http://www.diybl.com/course/6_system/linux/Linuxjs/200878/132342.html
platform_device的注册详情分析
http://blog.chinaunix.net/u1/39518/showart_423721.html
miscdevice、platform_device区别?
http://www.linuxfans.org/bbs/thread-178770-1-1.html
linux resouce,platform_device和platform_driver驱动的关系
http://linux.chinaunix.net/techdoc/develop/2008/03/12/982732.shtml
 
kobject研究
http://blog.chinaunix.net/u1/57901/showart_1803248.html
内外Input子系统
http://blog.chinaunix.net/u1/57901/showart_1073410.html
概括介绍Linux统一设备基本结构
http://os.51cto.com/art/200912/171772.htm
linux sysfs
http://blog.chinaunix.net/u3/101140/showart_2112847.html
Linux文件系统之sysfs
http://blog.chinaunix.net/u1/51562/showart_1076295.html
sysfs 文件系统
http://www.maycode.com/index.php/linux/34-linuxbase/1274-linux-fs.html
推荐博客
http://blog.chinaunix.net/u1/51562/article_86254.html
基于ARM含SD控制器的SD卡的SDIO模式驱动解析
http://blog.chinaunix.net/u1/49742/showart.php?id=1962481
ARM的CF卡驱动分析
http://blog.ednchina.com/gurongjiang/232138/message.aspx#
linux驱动设备注册
http://blog.chinaunix.net/u1/54524/showart_1982570.html
Linux设备驱动开发详解(非常好的linux驱动开发书籍)
http://book.chinaunix.net/showbook.php?id=100278
http://linux.chinaunix.net/bbs/thread-1130818-1-5.html
linux驱动模型分析总括
http://blog.csdn.net/yuanyou/archive/2009/01/08/3736747.aspx
Linux设备驱动模型之platform总线
http://blog.chinaunix.net/u2/72003/showart_1963302.html
浅析linux 2.6.23驱动注册函数driver_register()
http://blog.chinaunix.net/u3/110004/showart_2144965.html
 
 
如何利用Video4Linux获取摄像头数据
http://www.xxlinux.com/linux/article/accidence/internet/20060821/3708.html
obj-$(CONFIG_PXA_CAMERA) += camera.o ov7660.o ov2630.o ov3640.o ov9653.o ov7673.o ov5623.o
 
 
 
================
 
模块代码位置:
https://mohuifu.googlecode.com/svn/trunk/kernel_driver/moban_dirver
---------------------
/sys/bus/platform/drivers/moban_ts
moban_ts -> ../../../../devices/platform/moban_ts (/sys/devices/platform/moban_ts)
module -> ../../../../module/moban (/sys/module/moban/)
---------------------
/sys/bus/platform/devices
moban_ts -> ../../../devices/platform/moban_ts (/sys/devices/platform/moban_ts)
---------------------
图片很好的说明了各目录的层次关系:
http://linux.chinaunix.net/bbs/attachments/month_0901/20090119_15172562281c87a94b63IzL4u7uB2mM2.png
http://linux.chinaunix.net/bbs/attachments/month_0901/20090119_24fefe1d6080e5fc89d4st3ms2b4s4tz.png
驱动实例分析:
================
1. 声音,ALSA驱动程序开发
2. 蓝牙,WIFI驱动程序开发
3. 存储设备驱动程序开发
3. 视频,fb,摄像头,驱动开发
4. 电源管理驱动开发
5. 输入子系统驱动开发
 
================
 
 
============
3. 存储设备驱动程序开发
============
flash 驱动程序开发
==========
目前手机上使用的记忆卡有:CF、MMC、 SD、MINI-SD、 RS-MMC、T-Flash、MS、MS PRO、MS Duo九种。
CF卡(全名Compact Flash Card,常用于数码相机)
MMC卡(全名MultiMedia Card,也用于数码相机/手机等数码产品)
SD卡(全名为Secure Digital Memory Card,也用于数码相机/手机等数码产品)
miniSD卡(也可以插SD转换器后当SD卡使用)
RS-MMC卡(也叫mobile mmc卡,可插MMC卡转接器当MMC卡使用,NOKIA手机用的多)
TF卡(全名trans flash,也叫做micro SD卡,可插SD卡转换器变成SD卡使用,摩托罗拉手机比较常用这种存储卡)
MS卡(也叫记忆棒,索爱手机常用的存储卡)
================
下面我们了解一下这几种卡的规格。
===============
CF卡 即Compact Flash
一种袖珍闪存卡(尺寸为43mm*36mm*3.3mm),存储文件的速度比较快、存储容量适中,能耗低,在中、高档数字照
相机上应用比较多。CF存储卡的部分结构采用强化玻璃及金属外壳,CF存储卡采用Standard ATA/IDE接口界面,配
备有专门的PCM-CIA适配器(转接卡),笔记本电脑的用户可直接在PCMCIA插槽上使用,使数据很容易在数码相机与
电脑之间传递。目前最高容量可以达到8G。
============
MMC卡 即MultiMediaCard。
由西门子公司和首推CF的SanDisk于1997年推出。1998年1月十四家公司联合成立了MMC协会(MultiMediaCard
Association简称MMCA),现在已经有超过84个成员。MMC的发展目标主要是针对数码影像、音乐、手机、PDA、电子
书、玩具等产品,尺寸只有32mm x 24mm x 1.4mm,只有1.5克。MMC也是把存贮单元和控制器一同做到了卡上,智能
的控制器使得MMC保证兼容性和灵活性。
MMC存贮卡可以分为MMC和SPI两种工作模式,MMC模式是标准的默认模式,具有MMC的全部特性。而SPI模式则是MMC存
贮卡可选的第二种模式,这个模式是MMC协议的一个子集,主要用于只需要小数量的卡(通常是1个)和低数据传输率(和
MMC协议相比)的系统,这个模式可以把设计花费减到最小,但性能就不如MMC。
MMC被设计作为一种低成本的数据平台和通讯介质,它的接口设计非常简单:只有7针!接口成本低于0.5美元。在接口中,
电源供应是3针,而数据操作只用3针的串行总线即可(SPI模式再加上1针用于选择芯片)。
MMC的操作电压为2.7伏到3.6伏,写/读电流只有27mA和23mA,功耗很低。它的读写模式包括流式、多块和单块。最小
的数据传送是以块为单位的,缺省的块大小为512bytes。
MMC:感觉并不常用,存储速度和成本上对于SD卡没有优势,更多时候被SD卡替代,外观上和SD很相似,稍微薄一点
==============
SD卡 即Secure Digital Card卡
由松下、东芝和SanDisk联合推出,1999年8月才首次发布。于2000年2月1日发起成立了SD协会(Secure Digital
Association简称SDA),成员公司已经超过90个,阵容强大,其中包括IBM,Microsoft,Motorola,NEC、
Samsung等。
SD卡数据传送和物理规范由MMC发展而来,大小和MMC差不多,尺寸为32mm x 24mm x 2.1mm。长宽和MMC一样,只是
厚了0.7mm,以容纳更大容量的存贮单元。SD卡与MMC卡保持着向上兼容,也就是说,MMC可以被新的SD设备存取,兼容性
则取决于应用软件,但SD卡却不可以被MMC设备存取。(SD卡外型采用了与MMC厚度一样的导轨式设计,以使SD设备可以
适合MMC)SD接口除了保留MMC的7针外,还在两边加多了2针,作为数据线。采用了NAND型Flash Memory,基本上和
SmartMedia的一样,平均数据传输率能达到2MB/s
sd卡的结构能保证数字文件传送的安全性,也很容易重新格式化,所以有着广泛的应用领域,音乐、电影、新闻等多媒体
文件都可以方便地保存到sd卡中。因此不少数码相机也开始支持sd卡。
==============
MINI-SD卡 顾名思义, MINI
SD卡比目前主流的SD卡,在外形上更加小巧,重量仅有30克,体积只有21.5x20x1.4mm,比SD卡足足节省了60%的空间,
别小看这么小的外形,它可以让数码设备的体积节约40%空间。才能生产出更小的手机、DV等数码产品。在存储容量上,MINI
SD卡也丝毫不差,从的32MB到1GB各种规格一应俱全。随着消费数码产品的功能越来越大,用户对大容量存储卡的需求也日
益增长,目前的512M、1GB等容量已经在逐渐普及,未来还会成倍往上增长。MINI SD卡支持平均读写演算法( wear
leveling algorithms ),自动错误更正(ECC)等多种功能,使得MINI SD卡在使用寿命上更长,功耗更低。目前市面上
的MINI SD卡都支持MINI SD/SD Card(搭配转接卡)标准界面,在原有的SD卡设备上使用MINI SD卡变得非常方便,为
MINI SD卡的迅速普及铺平了道路
==============
RS-MMC卡 和MINI SD 卡一样, RS MMC卡也是一款投放市场不久的超小型闪存卡
==============
TF卡又称T-Flash卡,全名:TransFLash 又叫Micro SD,一种小型卡
由摩托罗拉与SANDISK共同研发,在2004年推出。是一种超小型卡(11*15*1MM),约为 SD卡的1/4,可以算目前最小的
储存卡了。TF卡可经SD卡转换器后,当SD卡使用。利用适配器可以在使用SD作为存储介质的设备上使用。 TransFlash主要
是为照相手机拍摄大幅图像以及能够下载较大的视频片段而开发研制的。TransFlash卡可以用来储存个人数据,例如数字照
片、MP3、游戏及用于手机的应用和个人数据等,还内设置版权保护管理系统,让下载的音乐、影像及游戏受保护;未来推出的
新型TransFlash还备有加密功能,保护个人数据、财政纪录及健康医疗文件。体积小巧的TransFlash让制造商无须顾虑电
话体积即可采用此设计,而另一项弹性运用是可以让供货商在交货前随时按客户不同需求做替换,这个优点是嵌入式闪存所没有的。
==============
其他比较老的卡
SmartMedia(SM卡)
XD-Picture Card(XD卡)
Memory Stick(记忆棒)
微硬盘(MICRODRIVE)
微型移动硬盘与U盘比较,移动硬盘优势明显
http://360.bolaa.com/forum/viewtopic_5682489_17967.html
 
 
static struct class mmc_host_class = {
.name = "mmc_host",
.dev_release = mmc_host_classdev_release,
};
 
 
./drivers/mmc/core/host.c:40: return class_register(&mmc_host_class);
./drivers/mmc/core/host.c:45: class_unregister(&mmc_host_class);
./drivers/mmc/core/host.c:80: host->class_dev.class = &mmc_host_class;
 
static struct platform_driver pxamci_driver = {
.probe = pxamci_probe,
.remove = pxamci_remove,
.suspend = pxamci_suspend,
.resume = pxamci_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
 
struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
...
dev_set_name(&host->class_dev, "mmc%d", host->index);
 
host->parent = dev;
host->class_dev.parent = dev;
host->class_dev.class = &mmc_host_class;
...
 
static int pxamci_probe(struct platform_device *pdev)
...
mmc = mmc_alloc_host(sizeof(struct pxamci_host), &pdev->dev);
...
mmc_add_host(mmc);
 
static int pxa9xx_mci_probe(struct platform_device *pdev)
...
mmc = mmc_alloc_host(sizeof(struct pxa9xx_mci_host), &pdev->dev);
...
mmc_add_host(mmc);
 
 
drivers/mmc/host/pxamci.c:47:#define DRIVER_NAME "pxa2xx-mci"
drivers/mmc/host/pxamci.c:881:MODULE_ALIAS("platform:pxa2xx-mci");
 
/sys/devices/platform/pxa2xx-mci.0/
/sys/bus/platform/drivers/moban_ts/ moban_ts 由moban_driver中的 name 指定
/sys/devices/platform/moban_ts/ moban_ts 由moban_driver中的 name 指定
 
 
 
 
===========
1. 声音,ALSA驱动程序开发
===========
ALSA 是 Advanced Linux Sound Architecture 的简称,译成中文的意思是 Linux 高级声音体系
1、对所有音频接口的高效支持,从普通用户的声卡到专业级别多路音频设备;
2、声卡驱动完全模块化设计;
3、SMP and thread-safe design.
4、开发库(alsa-lib) 为程序设计提供了简单、方便,并且拥有有高级的效果和功能;
5、支持旧版本的OSS API 结口,能为大多数的OSS应用程序提供兼容;
 
/lib/modules/2.6.27-4-generic/kernel/sound//pci/ac97/snd-ac97-codec.ko
/lib/modules/2.6.27-4-generic/kernel/sound/pci/snd-intel8x0.ko
/lib/modules/2.6.27-4-generic/kernel/sound/pci/snd-intel8x0m.ko
/lib/modules/2.6.27-4-generic/kernel/sound//ac97_bus.ko
/lib/modules/2.6.27-4-generic/kernel/sound//core/snd.ko
/lib/modules/2.6.27-4-generic/kernel/sound/pci
 
======================
aconnect 是一个用来连接和断开ALSA 音序器系统的两个端口的工具.
alsactl 用来控制ALSA声卡驱动的高级设置.
alsamixer 是一个基于ncurses的混合器程序,与 ALSA 声卡驱动共同使用.
amixer 允许ALSA 声卡驱动的命令行模式.
aplay 是ALSA驱动的命令行模式音频播放器.
arecord 是ALSA 驱动的命令行模式录音器.
aseqnet 是ALSA通过网络来接受和发送事件包的音序器客户端.
================================
示例,编译 amixer:
vendor/marvell/external/alsa/alsa-tools/amixer.c 源代码位置
===============================
target thumb C: amixer <= vendor/marvell/littleton/../external/alsa/alsa-tools/amixer.c
out/target/product/littleton/obj/EXECUTABLES/amixer_intermediates/amixer.o
target Executable: amixer (out/target/product/littleton/obj/EXECUTABLES/amixer_intermediates/LINKED/amixer)
target Non-prelinked: amixer (out/target/product/littleton/symbols/system/bin/amixer)
target Strip: amixer (out/target/product/littleton/obj/EXECUTABLES/amixer_intermediates/amixer)
Install: out/target/product/littleton/system/bin/amixer
================================
参考资料:
alsa-utils-0.9.2
alsa-utils 包含许多可以控制你的声卡的工具.
alsa-utils 依赖于 alsa-lib-0.9.2
alsa-driver-0.9.2 简单介绍alsa-driver
http://docs.huihoo.com/lfs/blfs-1.0/multimedia/alsa-driver.html
下载地址 (HTTP): http://www.alsa-project.org/alsa/ftp/driver/alsa-driver-0.9.2.tar.bz2
下载地址 (FTP): ftp://ftp.alsa-project.org/pub/driver/alsa-driver-0.9.2.tar.bz2
alsa-driver 包括ALSA声卡驱动程序.它是Linux的下一代声卡驱动程序.
关于多媒体的介绍:
http://docs.huihoo.com/lfs/blfs-1.0/multimedia/
 
 
 
/etc/modprobe.d/alsa-base
install sound-slot-0 /sbin/modprobe snd-card-0
install sound-slot-7 /sbin/modprobe snd-card-7
modinfo snd-intel8x0
descriptidescription: Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455on: Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455
 
 
首先要知道自己的声卡的芯片组,我们要通过lspci -v 来查看
只查看声卡的,应该用如下的方法:
lspci -v |grep audio
00:1f.5 Multimedia audio controller: Intel Corporation 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (rev 01)
Subsystem: IBM Device 055f
Flags: bus master, medium devsel, latency 0, IRQ 11
I/O ports at 1c00 [size=256]
I/O ports at 18c0 [size=64]
Memory at d0100c00 (32-bit, non-prefetchable) [size=512]
Memory at d0100800 (32-bit, non-prefetchable) [size=256]
Capabilities: <access denied>
Kernel driver in use: Intel ICH
Kernel modules: snd-intel8x0
通过上面的输出,我们知道这台机器用的是intel AC97声卡;所以我们要特别注意AC97的配置;
Device Drivers --->
<*> Sound card support ---> 声卡的支持,这个是一定要选中的吧
<*> OSS Mixer API
<*> OSS PCM (digital audio) API
[*] OSS PCM (digital audio) API - Include plugin system
<*> ALSA for SoC audio support --->
--- Sound card support
<*> Advanced Linux Sound Architecture ---> 对声卡支持的ALSA驱动的支持
--- ALSA for SoC audio support
SoC Audio for the Intel PXA3xx --->
[*] SoC Audio for the Intel PXA3xx chip
[*] SoC AC97 Audio support for Zylonite
[ ] SoC Audio support for Littleton
为什么没有选择littleton?
Generic devices ---> 进入里面
<M> Dummy (/dev/null) soundcard
<M> Virtual MIDI soundcard
<M> MOTU MidiTimePiece AV multiport MIDI
<M> UART16550 serial MIDI driver
<M> Generic MPU-401 UART driver
ISA devices ---> 如果您用ISA声卡就在这里面选;
PCI devices ---> 如果您用PCI声卡,就在这里面选,集成声卡也在这里;
USB devices ---> 这是USB声卡内核支持选项;我有一个这样的声卡,但没有试过;
PCMCIA devices ---> 这是PCMCIA声卡的选项,我还没有看过这样的声卡呢;如果您有,就在这里面动动手吧。
 
 
 
 
耳机:
asound.state_headphone_high
asound.state_headphone_low
asound.state_headset_high
asound.state_headset_low
asound.state_speaker_high
asound.state_speaker_low
 
asound.state_headset_mp3
asound.state_headset_r_s
asound.state_speaker_mp3
asound.state_speaker_r_mic_s
asound.state_receiver_r_mic_s
 
/etc/asound.state_speaker_mp3
/etc/asound.state_headset_r_s
/etc/asound.state_headset_mp3
/etc/asound.state_none
/etc/asound.state_headset_r_s
 
 
 
大部分的MP3音乐解压以后的编码也是44.1KHZ采样和16位编码的。从数据上看,CD和MP3的区别可以用码率的差别来体现。CD的码率是这么计算的:每秒钟的码率=44.1KHZ(采样率)*16(编码位数)*2(双声道)=1411.2Kbps。如果是某些采用48KHZ取样的音乐CD,其码率则为1536Kbps。而某些早期的某些单声道录音,码率是要除以2的。MP3的码率则是在这个基础上除以一个相关的压缩比例,这个数值一般大于4小于50,不难计算,我们一般从网上下载的192Kbps的MP3,所用的压缩比例大约是7.5左右。以上的数据可以用电脑软件来验证。如果用FOOBAR之类带码率显示的软件读取CD光盘和MP3,则可以很方便地看见码率
 
,CCITT规定抽样率为8KHz,每抽样值编8位码,即共有28=256个量化值,因而每话路PCM编码后的标准数码率是64kb/s
8*8
PCM基本工作原理
脉冲调制就是把一个时间连续,取值连续的模拟信号变换成时间离散,取值离散的数字信号后在信道中传输.脉冲编码调制就是对模拟信号先抽样,再对样值幅度量化,编码的过程.
所谓抽样,就是对模拟信号进行周期性扫描,把时间上连续的信号变成时间上离散的信号.该模拟信号经过抽样后还应当包含原信号中所有信息,也就是说能无失真的恢复原模拟信号.它的抽样速率的下限是由抽样定理确定的.在该实验中,抽样速率采用8Kbit/s.
所谓量化,就是把经过抽样得到的瞬时值将其幅度离散,即用一组规定的电平,把瞬时抽样值用最接近的电平值来表示.
一个模拟信号经过抽样量化后,得到已量化的脉冲幅度调制信号,它仅为有限个数值.
所谓编码,就是用一组二进制码组来表示每一个有固定电平的量化值.然而,实际上量化是在编码过程中同时完成的,故编码过程也称为模/数变换,可记作A/D.
PCM的原理如图5-1所示.话音信号先经防混叠低通滤波器,进行脉冲抽样,变成8KHz重复频率的抽样信号(即离散的脉冲调幅PAM信号),然后将幅度连续的PAM信号用"四舍五入"办法量化为有限个幅度取值的信号,再经编码后转换成二进制码.对于电话,CCITT规定抽样率为8KHz,每抽样值编8位码,即共有28=256个量化值,因而每话路PCM编码后的标准数码率是64kb/s.为解决均匀量化时小信号量化误差大,音质差的问题,在实际中采用不均匀选取量化间隔的非线性量化方法,即量化特性在小信号时分层密,量化间隔小,而在大信号时分层疏,量化间隔大.
在实际中广泛使用的是两种对数形式的压缩特性:A律和律.A律PCM用于欧洲和我国,律用于北美和日本.
 
比如电话就是3kHZ取样的7位声音,而CD是44.1kHZ取样的16位声音,所以CD就比电话更清楚。原本44.1K×16×2=1411.2 Kbps
以电话为例,每秒3000次取样,每个取样是7比特,那么电话的比特率是21000。而CD是每秒44100次取样,两个声道,每个取样是13位PCM编码,所以CD的比特率是44100*2*13=1146600,这个参数也被称为数据带宽,它和ADSL中的带宽是一个概念。将码率除以8,就可以得到这个它的数据速率,1146600/8=143325,也就是说CD每秒的数据量大约是144KB,而一张CD的容量是74分等于4440秒,就是 639360KB=640MB。即刚好为一张cd的容量
码率就是数据传输时单位时间传送的数据位数,一般我们用的单位是kbps即千位每秒。通俗一点的理解就是取样率,单位时间内取样率越大,精度就越高,处理出来的文件就越接近原始文件,但是文件体积与取样率是成正比的,即码率高,视频文件的何种就大,反之则小。帧率即每秒显示帧数,帧率表示图形处理器处理场时每秒钟能够更新的次数。高的帧率可以得到更流畅、更逼真的动画。一般来说30fps就是可以接受的,但是将性能提升至60fps则可以明显提升交互感和逼真感,但是一般来说超过75fps一般就不容易察觉到有明显的流畅度提升了。
码率和帧率不代表视频的播放速度,帧率的提高可使视频画面显得流畅,码率的提高可使画面更清晰,以上是摘自网络上一些文章,个人感觉是:
比特率(码率)=采样率(帧率)×采样位宽×声道数。
因此,比特率决定文件大小,即总信息量;而采样率决定文件播放流畅程度;位宽决定文件清晰程度。许多格式转换软件都可以设置比特率和采样率,在比特率一定的情况下,采样率越高,越流畅但越不清晰。
 
比特率这个词有多种翻译,比如码率等,表示经过编码(压缩)后的音频数据每秒钟需要用多少个比特来表示,而比特就是二进制里面最少的单位,要么是0,要么是1。比特率与音频压缩的关系简单的说就是比特率越高音质就越好,但编码后的文件就越大;如果比特率越少则情况刚好翻转。
VBR(Variable Bitrate)动态比特率 也就是没有固定的比特率,压缩软件在压缩时根据音频数据即时确定使用什么比特率,这是以质量为前提兼顾文件大小的方式,推荐编码模式;
ABR(Average Bitrate)平均比特率是VBR的一种插值参数。LAME针对CBR不佳的文件体积比和VBR生成文件大小不定的特点独创了这种编码模式。ABR在指定的文件大小内,以每50帧(30帧约1秒)为一段,低频和不敏感频率使用相对低的流量,高频和大动态表现时使用高流量,可以做为VBR和CBR的一种折衷选择。
CBR(Constant Bitrate),常数比特率 指文件从头到尾都是一种位速率。相对于VBR和ABR来讲,它压缩出来的文件体积很大,而且音质相对于VBR和ABR不会有明显的提高。
说白了比特率就是每秒钟传输的数位
比特率:也就是码率,指单位时间传输的或解码的位数,当然也可以换算成字节,数值越大越好,但是体积会变大的。
采样率:指每秒采集的次数,这个是指音频的,采的越多,声音质量越好,当然体积也会大。
视频分辨率:指每一帧画面的大小,宽乘高等于若干像素。
帧速:指播放时每秒移动多少帧。一般NTSC是30,PAL是25,帧速太低画面不连续.所以要愉到好处才行。
 
 
何谓音乐的比特率?
也可以叫码率,无非就是一种音乐每秒播放的数据量,单位用bit表示,也就是二进制位。 bps就是比特率。b就是比特(bit),s就是秒(second),p就是每(per),一个字节相当于8个二进制位。也就是说128bps的4分钟的歌曲的文件大小是这样计算的(128/8)*4*60=3840kB=3.8MB,也就是说同样比特率(bps)的同一歌曲不论是什么格式(如mp3 wma)容量大小都是基本一样的,这只能代表一种传输率,并不能代表音质,由于压缩引擎的不同,不同格式的音质又千差万别。但同格式来说比特率也高代表文件也就越大,相对来说音质也就越好。
 
何谓音乐的采样率?
采样率是指在单位时间的采样数。采样速率为44KHz,说明每秒采样数量为44K个,这是也就是用44000个数据来描述1秒内的声音波形。也就是说采样率越高音质也是越好。但是他同比特率是完全不同的两个概念。
采样率.和比特率是两个概念.比特率是每秒播放的数据量.采样率是每秒内的声音波形.一般44K也就是用44000个数据来描述一秒内的声音波形.只有采样率高的的音乐音质也就越高.
 
计算机中的信息都是二进制的0和1来表示,其中每一个0或 1被称作一个位,用小写b表示,即bit(位);大写B表示byte,即字节,一个字节=八个位,即1B=8b;前面的大写K表示千的意思,即千个位(Kb)或千个字节(KB)。表示文件的大小单位,一般都使用字节(KB)来表示文件的大小。
Kbps:首先要了解的是,ps指的是/s,即每秒。Kbps指的是网络速度,也就是每秒钟传送多少个千位的信息(K表示千位,Kb表示的是多少千个位),为了在直观上显得网络的传输速度较快,一般公司都使用kb(千位)来表示,如果是KBps,则表示每秒传送多少千字节。1KBps=8Kbps。 ADSL上网时的网速是512Kbps,如果转换成字节,就是512/8=64KBps(即64千字节每秒)。
 
帧数简单地说,帧数就是在1秒钟时间里传输的图片的帧数,也可以理解为图形处理器每秒钟能够刷新几次,通常用fps(Frames Per Second)表示。每一帧都是静止的图象,快速连续地显示帧便形成了运动的假象。高的帧率可以得到更流畅、更逼真的动画。每秒钟帧数 (fps) 愈多,所显示的动作就会愈流畅。一般来说30fps是可以接受的,所以要避免动作不流畅的最低fps是30。除了30fps外,有些计算机视频格式,例如 AVI,每秒只能提供15帧。我们之所以能够利用摄像头来看到连续不断的影像,是因为影像传感器不断摄取画面并传输到屏幕上来,当传输速度达到一定的水平时,人眼就无法辨别画面之间的时间间隙,所以大家可以看到连续动态的画面。
每秒的帧数(fps)或者说帧率表示图形处理器场景时每秒钟能够更新几次。高的帧率可以得到更流畅、更逼真的动画。一般来说30fps就是可以接受的,但是将性能提升至60fps则可以明显提升交互感和逼真感,但是一般来说超过75fps一般就不容易察觉到有明显的流畅度提升了。如果帧率超过屏幕刷新率只会浪费图形处理的能力,因为显示器不能以这么快的速度更新,这样超过刷新率的帧率就浪费掉了。
一般用“FPS(frame per second,每秒钟画面更新的数量)”来表示该项指标。在欣赏电视、电影画面时,只要画面的刷新率达到24帧/秒,就能满足人们的需要。同样的,在玩普通的游戏时,如果刷新率达到24帧/秒即可,但在一些高速游戏中(例如射击游戏),如果画面的刷新率还是只有24帧/秒,那么就会感觉到画面比较迟钝,不够流畅。
  虽然理论上画面的刷新率越快越好,但过高的刷新率并没有实际意义——当画面的FPS达到60帧/秒时,已经能满足绝大部分应用需求。一般情况下,如果能够保证游戏画面的平均FPS能够达到30帧/秒,那么画面已经基本流畅;能够达到50帧/秒,就基本可以体会到行云流水的感觉了。一般人很难分辨出60 帧/秒与100帧/秒有什么不同。
 
电脑中所显示的画面,都是由显卡来进行输出的,因此屏幕上每个像素的填充都得由显卡来进行计算、输出。当画面的分辨率是1024×768时,画面的刷新率要达到24帧/秒,那么显卡在一秒钟内需要处理的像素量就达到了“1024×768×24=18874368”。如果要求画面的刷新率达到50 帧/秒,则数据量一下子提升到了“1024×768×50=39321600”。
 
  FPS与分辨率、显卡处理能力的关系如下:处理能力=分辨率×刷新率。这也就是为什么在玩游戏时,分辨率设置得越大,画面就越不流畅的原因了。
 
音频处理介绍(Linux手机)
驱动程序导读
http://blog.csdn.net/absurd/archive/2007/11/07/1872258.aspx
sound/arm/codec/ac97acodec.c包装了对AC97寄存器的读写操作,zy_ac97_acodec_write向指定的偏移量写入数据,zy_ac97_acodec_read从指定的偏移量读取数据。& (p_ac97_reg->codec_regs_primary_aud[0])是寄存器的基址。
sound/arm/codec/acodec.c 提供codec的初始化和~初始化以及电源管理的suspend和resume函数。AC97的PIN配置可以参考arch/arm/mach-pxa/zylonite.c:zylonite_ac97_pins。
sound/arm/codec/lt*是marvell另外一个硬件平台Littleton的驱动。
sound/arm /codec/wm9713.c,这里面主要是对AC97控制功能的包装,提供比如像设置音量之类的函数,zy_acodec_set_pen_down_interrupt/zy_wm9713_enable_touch/zy_wm9713_disable_touch/zy_wm9713_disable_touch 几个函数用于触摸屏控制和采样。
sound/arm/codec/wm9713_bb.c好像是用于BaseBand的,里面的内容与wm9713类似,具体差别还不是很清楚,希望哪位高手能告知。有时间再研究一下。
sound/arm/mhn_audio_card.c 声卡驱动入口,提供audio_codec_zy_driver结构,通过driver_register注册到内核里去,在audio_codec_zy_probe函数中创建声卡对象,并注册到ALSA框架中。
sound/arm/mhn_audio_control.c 对codec/wm9713.c中的函数进一步包装,通过audio_codec_control_new为声卡创建一个控制对象。
sound/arm/mhn_audio_pcm.c 对PCM对象进行包装,audio_codec_pcm_new中可以创建HIFI PCM和Voice PCM,两个的差别,我不太清楚,希望哪位高手能告知。SSP的初始化和~初始化也是在这里做的。
sound/arm/mhn_audio_voice_pcm.c 实现了voice PCM对象,其核心就是结构voice_pcm_ops,该结构中最重要的成员是voice_pcm_trigger,voice_pcm_trigger负责DMA传输的起动和停止。
sound/core/pcm_native.c 对下层的PCM驱动提供包装,为上层提供统一的接口,snd_pcm_f_ops_playback文件操作结构提供播放功能的函数,snd_pcm_f_ops_capture文件操作结构提供录音功能的函数。
sound/core/control.c对下层的Control驱动提供包装,为上层提供统一的接口,snd_ctl_f_ops文件操作结构提供控制功能函数,其中主要是snd_ctl_ioctl函数。
播放的过程大致如下:
Snd_pcm_f_ops_playback.write即snd_pcm_write调用snd_pcm_lib_write
snd_pcm_lib_write调用Snd_pcm_lib_write1
Snd_pcm_lib_write1通过snd_pcm_lib_write_transfer把数据写入DMA buffer中,然后调用snd_pcm_start开始DMA传输数据到WM9713里去。
录音的过程大致如下:
Snd_pcm_f_ops_capture.read即snd_pcm_read调用snd_pcm_lib_read
snd_pcm_lib_read调用snd_pcm_lib_read1
snd_pcm_lib_read1调用snd_pcm_start从WM9713传输数据到DMA内存中,然后调用snd_pcm_lib_read_transfer拷贝数据到用户的buffer.
 
 
 
Beyond Linux From Scratch: 版本 1.0
http://docs.huihoo.com/lfs/blfs-1.0/multimedia/alsa-driver.html
多媒体库文件和驱动程序
目录
alsa-0.9.2
alsa-driver-0.9.2
alsa-lib-0.9.2
alsa-utils-0.9.2
alsa-tools-0.9.1
alsa-oss-0.9.1
alsa-driver 包括ALSA声卡驱动程序.它是Linux的下一代声卡驱动程序.
alsa-driver 包括alsa 声卡驱动程序和 头文件
头文件安装在 /usr/include/sound并且在编译其他包的时候要用到的文件,比如alsa-lib.
http://docs.huihoo.com/lfs/blfs-1.0/multimedia/alsa-lib.html
alsa-lib 包括包包括 alsa 库文件. 用到alsa声音接口的程序(包括alsa-utils) 需要用到.
alsa-lib 依赖于 alsa-driver-0.9.2 里安装的头文件
alsa-lib 包括 aserver和 alsa library.
alsa-tools 包含一些声卡的高级设置工具.
alsa-tools 依赖于 alsa-lib-0.9.2
在这个包中包含的工具是 ac3dec, as10k1, envy24control, sb16_csp和sbiload.
http://docs.huihoo.com/lfs/blfs-1.0/multimedia/alsa-utils.html
alsa-utils 包含许多可以控制你的声卡的工具.
alsa-utils 包括 aconnect, alsactl, alsamixer, amixer, aplay, arecord和aseqnet.
http://docs.huihoo.com/lfs/blfs-1.0/multimedia/alsa-oss.html
alsa-oss 包括 alsa oss 兼容库,对于使用 alsa oss 声音接口的程序很有用。
alsa-oss 包括 aoss 和 alsa oss 兼容库.
以上为中文版本,最新资料可以 6.3 英文稳定版本或者 svn 版本
Beyond Linux® From Scratch Version 6.3
http://www.linuxfromscratch.org/blfs/view/stable/multimedia/libdriv.html
Beyond Linux® From Scratch Version svn-2009xxxx
http://www.linuxfromscratch.org/blfs/view/svn/
http://cross-lfs.org/view/clfs-embedded/
 
对文件 patching file vendor/marvell/littleton/libaudio/AudioHardwareLittleton.cpp 所作的修改
void enable_hifi_mono(unsigned char vol)
{
system("alsactl -f /etc/asound.state_none restore");
system("alsactl -f /etc/asound.state_speaker_mp3 restore");
}
void enable_hifi_bear(unsigned char vol)
{
//system("alsactl -f /etc/asound.state_headset_high restore");
system("alsactl -f /etc/asound.state_none restore");
system("alsactl -f /etc/asound.state_headset_r_s restore");
}
 
void enable_hifi_headset(unsigned char vol)
{
 
//system("alsactl -f /etc/asound.state_headset_high restore");
system("alsactl -f /etc/asound.state_none restore");
system("alsactl -f /etc/asound.state_headset_mp3 restore");
}
void enable_incall_headphone(unsigned char vol)
{
LOGI("================= enable_incall_headphone ===============\n");
system("alsactl -f /etc/asound.state_none restore");
system("alsactl -f /etc/asound.state_headset_r_s restore");
}
void enable_voice_mic1(unsigned char vol)
{
LOGI("================= enable_voice_mic1 ======================\n");
system("alsactl -f /etc/asound.state_none restore");
system("alsactl -f /etc/asound.state_headset_r_s restore");
}
 
status_t AudioHardwareMarvell::doRouting()
case AudioSystem::MODE_IN_CALL:
LOGI("--hd--MODE_IN_CALL-----\n");
enable_incall_headphone(nv);
enableAlsaDevice(sHIFI);
/* Not support yet */
break;
以上多媒体相关
=====================================================================================
 
 
 
 
 
 
=============
2. 蓝牙,WIFI驱动程序开发
=============
知识点
 
蓝牙相关
在嵌入式开发板上移植蓝牙主要涉及到
 
 
内核中蓝牙协议的配置:
内核的配置,基本上把 networking下 --- Bluetooth subsystem support 里的以下几项全部选上即可:
L2CAP protocol support
SCO links support
RFCOMM protocol support
RFCOMM TTY support
BNEP protocol support
HIDP protocol support
此外,在Bluetooth device drivers里选上你所需要支持的Bluetooth设备。我使用的CSR的chip是我们直接build在板子上,通过串口和cpu通讯的,芯片默认使用BCSP作为通讯协议,所以我选择了:
HCI UART driver
BCSP protocol support
如果你是通过usb接口使用蓝牙适配器,需要选择
HCI USB driver
 
-> Networking
│ -> Networking support (NET [=y])
│ -> Bluetooth subsystem support (BT [=y])
│ -> Bluetooth device drivers
│ -> HCI UART driver (BT_HCIUART [=y])
 
 
Bluez版本:bluez-libs 3.22 bluez-utils 3.22
bluez-libs 3.22 bluez-utils 3.22
蓝牙协议等资源下载网址:
http://www.bluez.org/download/
http://bluez.sf.net/download/bluez-libs-3.36.tar.gz
http://bluez.sf.net/download/bluez-utils-3.36.tar.gz
http://www.kernel.org/pub/linux/bluetooth/obexd-0.8.tar.gz
http://tadas.dailyda.com/software/obex-data-server-0.4.2.tar.gz
 
libdbus-1-3
libdbus-glib-1-2
 
 
 
root@192:/usr/etc/bluetooth$ rfcomm conn /dev/rfcomm0 77:86:34:3C:66:01 10
Can't connect RFCOMM socket: Operation now in progress
 
 
 
OBEX是Object Exchang的简称,本来是IrDA™为红外传输制定的协议,但它并不限于特定的底层传输方式,可以运行于blueteeth、usb和tcp/ip其它多种协议之上。OBEX主要是会话层协议,同时也包括应用层部分功能。它可以传输任何对象,在手机中,通常用来传输文件、图片、名片(Vcard)和日程(Vcal)等。OpenOBEX是一套开放源代码的OBEX协议实现,提供client和server两端的功能
http://www.builder.com.cn/2008/0127/722148.shtml
 
蓝牙操作
hciconfig -a
hciconfig hci0 up
sudo /usr/gpephone/sbin/hciconfig hci0 up
/usr/gpephone/bin/hcitool scan
 
 
 
 
参考资料:
 
http://www.unixresources.net/linux/clf/embedded/archive/00/00/68/72/687201.html
====================
 
 
 
===============
3. 视频,fb,摄像头,驱动开发
===============
2.1.1 LCD配置相关
#Graphics support
CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
 
# Frame buffer hardware drivers
CONFIG_FB_PXA=y
CONFIG_FB_PXA_OVERLAY=y
# CONFIG_FB_PXA_MINILCD is not set
# CONFIG_FB_PXA_LCD_QVGA is not set
CONFIG_FB_PXA_LCD_VGA=y
CONFIG_FB_PXA_LCD_16BPP=y
# CONFIG_FB_PXA_LCD_18BPP is not set
# CONFIG_FB_PXA_LCD_19BPP is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_MICCO=y
CONFIG_BACKLIGHT_PXA3XX_PWM=y
CONFIG_BACKLIGHT_PXA3XX_GPIO=y
屏幕使用的是 VGA
 
CONFIG_FB_PXA_LCD_QVGA=y
CONFIG_FB_PXA_LCD_VGA=y
 
 
CONFIG_FB_PXA_LCD_VGA=y
CONFIG_FB_PXA_LCD_16BPP=y
 
 
 
 
 
触摸屏幕配置
static void __init littleton_init(void)
wm9713_touch_resources[0].start = NULL;//gpio_to_irq(gpio_touch_irq);
wm9713_touch_resources[0].end = NULL;//gpio_to_irq(gpio_touch_irq);
platform_device_register(&wm9713_touch_device);
 
 
背光显示驱动
CONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_CORGI is not set
# CONFIG_BACKLIGHT_PWM is not set
CONFIG_BACKLIGHT_MICCO=y
# CONFIG_BACKLIGHT_MICCO_KP is not set
CONFIG_BACKLIGHT_PXA3XX_PWM=y
CONFIG_BACKLIGHT_PXA3XX_GPIO=y
 
 
CONFIG_FB_PXA_LCD_16BPP=y
 
 
│ Symbol: FB_PXA_LCD_VGA [=y]
│ Prompt: VGA (640x480)
│ Defined at drivers/video/Kconfig:1843
│ Depends on: <choice>
│ Location:
│ -> Device Drivers
│ -> Graphics support
│ -> Support for frame buffer devices (FB [=y])
│ -> PXA LCD framebuffer support (FB_PXA [=y])
│ -> LCD type (<choice> [=y])
 
 
Symbol: BACKLIGHT_LCD_SUPPORT [=y]
│ Prompt: Backlight & LCD device support
│ Defined at drivers/video/backlight/Kconfig:5
│ Depends on: HAS_IOMEM
│ Location:
│ -> Device Drivers
│ -> Graphics support
│ Selected by: THINKPAD_ACPI && MISC_DEVICES && X86 && ACPI || FB_BACKLIGHT && HAS_IOMEM && FB || USB_APP
 
 
│ Symbol: FB_PXA_LCD_16BPP [=y]
│ Prompt: 16bpp (RGB565)
│ Defined at drivers/video/Kconfig:1852
│ Depends on: <choice>
│ Location:
│ -> Device Drivers
│ -> Graphics support
│ -> Support for frame buffer devices (FB [=y])
│ -> PXA LCD framebuffer support (FB_PXA [=y])
│ -> Pixel format (<choice> [=y])
 
==============
内核中 marvell lcd相关的参数
linux-2.6.21/arch/arm/mach-pxa/littleton.c
#ifdef CONFIG_FB_PXA_LCD_VGA
static struct pxafb_mach_info tpo_tdo24mtea1_vga __initdata = {
.pixclock = 38250,
.xres = 480,
.yres = 640,
.bpp = 16,
.hsync_len = 8,
.left_margin = 8,
.right_margin = 24,
.vsync_len = 2,
.upper_margin = 2,
.lower_margin = 4,
.sync = 0,
.lccr0 = LCCR0_Act,
.lccr3 = LCCR3_HSP | LCCR3_VSP,
.pxafb_backlight_power = littleton_backlight_power,
.pxafb_lcd_power = littleton_lcd_power,
};
#endif /* CONFIG_FB_PXA_LCD_VGA */
 
#ifdef CONFIG_FB_PXA_LCD_QVGA
static struct pxafb_mach_info tpo_tdo24mtea1_qvga __initdata = {
.pixclock = 153000,
.xres = 240,
.yres = 320,
.bpp = 16,
.hsync_len = 8,
.left_margin = 8,
.right_margin = 88,
.vsync_len = 2,
.upper_margin = 2,
.lower_margin = 2,
.sync = 0,
.lccr0 = LCCR0_Act,
.lccr3 = LCCR3_HSP | LCCR3_VSP,
.pxafb_backlight_power = littleton_backlight_power,
.pxafb_lcd_power = littleton_lcd_power,
};
#endif /* CONFIG_FB_PXA_LCD_QVGA */
 
 
Littleton.c (linux-2.6.28\arch\arm\mach-pxa)
目录我们使用的屏幕
static struct pxafb_mode_info lg4571_lcd_vga[] = {
[0] = {
.pixclock = 40850,
.xres = 480,
.yres = 800,
.bpp = 16,
.hsync_len = 1,
.left_margin = 19,//88
.right_margin = 0,//
.vsync_len = 1,
.upper_margin = 15,//16
.lower_margin = 0,
.sync = 0,
},
};
 
static struct pxafb_mach_info littleton_lcd_info = {
.modes = lg4571_lcd_vga,
.num_modes = 1,
.lccr0 = LCCR0_Act,
.lccr3 = LCCR3_PCP | LCCR3_HSP | LCCR3_VSP,
.pxafb_lcd_power = littleton_lcd_power,
};
 
static void littleton_init_lcd(void)
{
set_pxa_fb_info(&littleton_lcd_info);
}
 
static void __init littleton_init(void)
...
littleton_init_lcd();
...
 
./drivers/video/pxafb.c:1712: set_ctrlr_state(fbi, C_ENABLE_PM);
 
static struct platform_driver pxafb_driver = {
.probe = pxafb_probe,
#ifdef CONFIG_PM
.suspend = pxafb_suspend,
.resume = pxafb_resume,
#endif
.driver = {
.name = "pxa2xx-fb",
},
};
 
 
static int pxafb_resume(struct platform_device *dev)
{
struct pxafb_info *fbi = platform_get_drvdata(dev);
 
set_ctrlr_state(fbi, C_ENABLE_PM);
return 0;
}
 
drivers/media/video/pxa3xx/camera.c:3059: cam_ctx->platform_ops->resume();
drivers/usb/musb/musb_gadget.c:1882: musb->gadget_driver->resume(&musb->g);
drivers/usb/gadget/pxa25x_udc.c:1756: dev->driver->resume(&dev->gadget);
 
CONFIG_USB_GADGET_PXA3XX_U2D=y
CONFIG_USB_PXA3XX_U2D=y
 
 
================
 
Littleton.c (linux-2.6.28\arch\arm\mach-pxa):
MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
.phys_io = 0x40000000,
.boot_params = 0xa0000100,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa3xx_init_irq,
.timer = &pxa_timer,
.init_machine = littleton_init,
MACHINE_END
 
littleton_init->littleton_init_nand->platform_device_register(&pxa3xx_device_nand);
 
Pxa3xx_nand.c (linux-2.6.28\drivers\mtd\nand)
static int __init pxa3xx_nand_init(void)
module_init(pxa3xx_nand_init);
pxa3xx_nand_init->platform_driver_register(&pxa3xx_nand_driver);
static struct platform_driver pxa3xx_nand_driver = {
.driver = {
.name = "pxa3xx-nand",
},
.probe = pxa3xx_nand_probe,
.remove = pxa3xx_nand_remove,
#ifdef CONFIG_PM
.suspend = pxa3xx_nand_suspend,
.resume = pxa3xx_nand_resume,
#endif
};
 
 
static struct fb_ops overlay1fb_ops = {
.owner = THIS_MODULE,
.fb_open = overlay1fb_open,
.fb_release = overlay1fb_release,
.fb_check_var = overlay1fb_check_var,
.fb_set_par = overlay1fb_set_par,
.fb_blank = overlay1fb_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_cursor = soft_cursor,
};
 
 
static struct fb_ops overlay2fb_ops = {
.owner = THIS_MODULE,
.fb_open = overlay2fb_open,
.fb_release = overlay2fb_release,
.fb_check_var = overlay2fb_check_var,
.fb_set_par = overlay2fb_set_par,
.fb_blank = overlay2fb_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_cursor = soft_cursor,
.fb_pan_display = pxafb_pan_display,
};
 
static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
__acquires(&info->lock)
__releases(&info->lock)
{
struct inode *inode = file->f_path.dentry->d_inode;
int fbidx = iminor(inode);
struct fb_info *info;
long ret;
 
info = registered_fb[fbidx];
mutex_lock(&info->lock);
ret = do_fb_ioctl(info, cmd, arg);
mutex_unlock(&info->lock);
return ret;
}
ypanstep
static const struct file_operations fb_fops = {
.owner = THIS_MODULE,
.read = fb_read,
.write = fb_write,
.unlocked_ioctl = fb_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = fb_compat_ioctl,
#endif
.mmap = fb_mmap,
.open = fb_open,
.release = fb_release,
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
.get_unmapped_area = get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO
.fsync = fb_deferred_io_fsync,
#endif
};
fbmem_init->register_chrdev(FB_MAJOR,"fb",&fb_fops)
 
 
CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_PXA=y
CONFIG_FB_PXA_OVERLAY=y
CONFIG_FB_PXA_LCD_VGA=y
CONFIG_FB_PXA_LCD_16BPP=y
obj-$(CONFIG_VGASTATE) += vgastate.o
obj-y += fb_notify.o
obj-$(CONFIG_FB) += fb.o
fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
modedb.o fbcvt.o
fb-objs := $(fb-y)
obj-y += backlight/ display/
 
 
fb初始化相关:
#ifdef MODULE
module_init(fbmem_init);
#else
subsys_initcall(fbmem_init);
#endif
module_init(pxafb_init);
module_init(pxafb_overlay_init);
 
 
Fbmem.c (d:\cupcake-jianping\linux-2.6.28\drivers\video):
EXPORT_SYMBOL(register_framebuffer);
EXPORT_SYMBOL(unregister_framebuffer);
EXPORT_SYMBOL(num_registered_fb);
EXPORT_SYMBOL(registered_fb);
EXPORT_SYMBOL(fb_show_logo);
EXPORT_SYMBOL(fb_set_var);
EXPORT_SYMBOL(fb_blank);
EXPORT_SYMBOL(fb_pan_display);
EXPORT_SYMBOL(fb_get_buffer_offset);
EXPORT_SYMBOL(fb_set_suspend);
EXPORT_SYMBOL(fb_get_options);
 
int register_framebuffer(struct fb_info *fb_info)
fb_info->dev = device_create(fb_class, fb_info->device,MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
dev_set_drvdata(dev, drvdata);
retval = device_register(dev);
return device_add(dev);
error = bus_add_device(dev);
bus_attach_device(dev);
registered_fb[i] = fb_info;
int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
err = info->fbops->fb_pan_display(var, info)
 
 
Pxafb.c (d:\cupcake-jianping\linux-2.6.28\drivers\video):
static int __init pxafb_probe(struct platform_device *dev)
fbi = pxafb_init_fbinfo(&dev->dev);
fbi->dev = dev;
fbi->fb.fbops = &pxafb_ops;
/* Initialize video memory */
ret = pxafb_map_video_memory(fbi);
ret = request_irq(IRQ_LCD, pxafb_handle_irq, IRQF_DISABLED, "LCD", fbi);
ret = register_framebuffer(&fbi->fb);
Pxafb_overlay.c (d:\cupcake-jianping\linux-2.6.28\drivers\video):
static int __devinit pxafb_overlay_init(void)
dev = find_bus_device(&platform_bus_type, "pxa2xx-fb");
overlay1fb = overlay1fb_init_fbinfo();
ret = register_framebuffer(&overlay1fb->fb);
overlay2fb = overlay2fb_init_fbinfo();
ret = register_framebuffer(&overlay2fb->fb);
cursorfb = cursorfb_init_fbinfo();
ret = register_framebuffer(&cursorfb->fb);
 
 
int rotatefb_main(int argc, char *argv[])
res = ioctl(fd, FBIOGET_VSCREENINFO, &fbinfo);
 
status_t system_init()
SurfaceFlinger::instantiate();
defaultServiceManager()->addService(String16("SurfaceFlinger"), new SurfaceFlinger());
 
#define BASE_FB_DEVICE "/dev/graphics/fb0"
#define OVERLAY2_FB_DEVICE "dev/graphics/fb2"
 
 
 
----------------------------------
显示logo信息:
static const struct consw fb_con = {
.owner = THIS_MODULE,
.con_startup = fbcon_startup,
.con_init = fbcon_init,
...
}
static int __init fb_console_init(void)
fbcon_start();
fbcon_takeover(0);
err = take_over_console(&fb_con, first_fb_vc, last_fb_vc,fbcon_is_default);
步骤一:
console_initcall(con_init);
#define console_initcall(fn) static initcall_t __initcall_##fn \
__attribute_used__ __attribute__((__section__(".con_initcall.init")))=fn
static int __init con_init(void)
visual_init(vc, currcons, 1);
vc->vc_sw->con_init(vc, init);
vc->vc_sw->con_init 调用的是:
static void fbcon_init(struct vc_data *vc, int init)
if (logo)
fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
logo_shown = FBCON_LOGO_DRAW;
vc->vc_top = logo_lines;
步骤二:
static int __init con_init(void)
update_screen(vc);
因为有:
void redraw_screen(struct vc_data *vc, int is_switch);
#define update_screen(x) redraw_screen(x, 0)
#define switch_screen(x) redraw_screen(x, 1)
所以调用:
void redraw_screen(struct vc_data *vc, int is_switch)
update = vc->vc_sw->con_switch(vc);
fb_show_logo(info, ops->rotate);
----------------------------------
Device Drivers --->
Graphics support --->
<*> Support for frame buffer devices --->
<*> PXA LCD framebuffer support
<*> LCD overlay support
LCD type (VGA (640x480)) --->
Pixel format (16bpp (RGB565)) --->
[*] Backlight & LCD device support --->
 
 
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(), Thread(false),
mTransactionFlags(0),
mTransactionCount(0),
mBootTime(systemTime()),
mLastScheduledBroadcast(NULL),
mVisibleRegionsDirty(false),
mDeferReleaseConsole(false),
mFreezeDisplay(false),
mFreezeCount(0),
mFreezeDisplayTime(0),
mDebugRegion(0),
mDebugCpu(0),
mDebugFps(0),
mDebugBackground(0),
mDebugNoBootAnimation(0),
mSyncObject(),
mDeplayedTransactionPending(0),
mConsoleSignals(0),
mSecureFrameBuffer(0)
{
init();
}
 
因为 class SurfaceFlinger : public BnSurfaceComposer, protected Thread
status_t Thread::run(const char* name, int32_t priority, size_t stack)
在run中创建了线程 _threadLoop
 
int Thread::_threadLoop(void* user)
self->mStatus = self->readyToRun();
readyToRun 实际调用的是 SurfaceFlinger 中的函数 readyToRun
status_t SurfaceFlinger::readyToRun()
DisplayHardware* const hw = new DisplayHardware(this, dpy);
 
void DisplayHardware::init(uint32_t dpy)
mDisplaySurface = new EGLDisplaySurface();
egl_native_window_t* android_createDisplaySurface()
egl_native_window_t* s = new android::EGLDisplaySurface();
 
 
EGLDisplaySurface::EGLDisplaySurface()
egl_native_window_t::fd = mapFrameBuffer();
status_t EGLDisplaySurface::mapFrameBuffer()
info.yres_virtual = info.yres * 2;
 
Framebuffer_service.c (\system\core\adb):
void framebuffer_service(int fd, void *cookie)
fbinfo[1] = vinfo.xres * vinfo.yres * 2;
 
 
static void pxafb_setmode(struct fb_var_screeninfo *var, struct pxafb_mode_info *mode)
Pxafb.c (d:\cupcake-jianping\linux-2.6.28\drivers\video):
static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
fbi->fb.var.yres_virtual = mode->yres * 2;
Pxafb_minilcd.c (d:\cupcake-jianping\linux-2.6.28\drivers\video):
int pxafb_minilcd_enter( void )
sram_size = (fbi->fb.var.xres + 1) * fbi->fb.var.yres * 2;
Rotatefb.c (d:\cupcake-jianping\system\core\toolbox):
int rotatefb_main(int argc, char *argv[])
 
 
 
 
==========
4. 电源管理驱动开发
==========
cpu 动态调频相关
========
cd /sys/devices/system/cpu/cpu0
cat /sys/devices/system/cpu/cpu0/op
echo "1">/sys/devices/system/cpu/cpu0/op
echo "2">/sys/devices/system/cpu/cpu0/op
echo "4">/sys/devices/system/cpu/cpu0/op
 
echo "4">/sys/devices/system/cpu/cpu0/op
echo "3">/sys/devices/system/cpu/cpu0/op
 
echo "0">/sys/devices/system/cpu/cpu0/op
cat /sys/devices/system/cpu/cpu0/op
 
cat /sys/devices/system/cpu/cpu0/op
cat /sys/devices/system/cpu/cpu0/ops
echo "2">op
查看
cat /sys/devices/system/cpu/cpu0/op
关掉
echo "0">/sys/power/mspm/prof
========
 
 
 
 
===========
5. 输入子系统驱动开发
===========
修改前的内核:
启动的时候没插入耳机
GPIO-80 autorequested
GPIO-81 autorequested
headset.state=0
待机后插入耳机
headset.state=0
headset.state=0
.........gpio= 104
.........state= 256
headset.state=256
not headset keypad
headset.state=256
keypad down
headset.state=256
keypad up
拔掉耳机:
bash-3.2# .........gpio= 104
.........state= 0
快速插入耳机:
headset.state=0
headset.state=0
.........gpio= 104
.........state= 256
headset.state=256
not headset keypad
headset.state=256
not headset keypad
拔掉耳机:
bash-3.2# .........gpio= 104
.........state= 0
===============
启动的时候插入耳机
GPIO-80 autorequested
GPIO-81 autorequested
headset.state=256
not headset keypad
待机后拔掉耳机:
bash-3.2# headset.state=256
keypad down
.........gpio= 104
.........state= 0
headset.state=0
 
快速拔掉耳机:
 
 
 
=======================
插入耳机:
headset.state=0
.........gpio= 104
.........state= 256
V/HeadsetObserver( 80): Headset UEVENT: {SWITCheadset.state=256
H_STATE=1, SWITCH_NAME=h2w, ACTION=change, SEQNU not headset keypad
M=794, DEVPATH=/class/switch/h2w, SUBSYSTEM=switch}
D/IconMerger( 80): IconMerger width icon_num346 5
D/StatusIconArray( 80): StatusIconArray width icon_num67 5
D/PhoneApp( 127): mReceiver: ACTION_HEADSET_PLUG
D/PhoneApp( 127): state: 1
D/PhoneApp( 127): name: h2w
I/AudioManager( 80): +++++++++++++++++++ AudioManager.java: setRouting(): mode=0,routes=8,mask=-17
I/AudioManager( 80): AudioManager: setRouting...
I/AudioService( 80): AudioService.java: setRouting(): mode= 0, routes=8 ,mask=-17
I/AudioService( 80): AudioService.java: setRouting(): ---1--
I/AudioSystem( 80): hd: AudioSystem.cpp: here?
I/AudioSystem( 80): hd: AudioSystem.cpp: setRouting(0, 8, 4294967279)
I/AudioFlinger( 44): hd: AudioFlinger.cpp: setRouting(0, 8, 4294967279)
D/AudioFlinger( 44): hd: setRouting 0 8 -17, tid 73, calling tid 80
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::getRouting(0)***************************
I/AudioHardwareLittleton( 44): *************************AudioHardwareMarvell::setRouting(0,8)*******************
********
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::doRouting(0, 2, 0, 8)***********************
****
I/AudioHardwareLittleton( 44): #################################
I/AudioHardwareLittleton( 44): ######### doRouting ###########
I/AudioHardwareLittleton( 44): #################################
I/AudioHardwareLittleton( 44): ===== Audio Path: MODE_NORMAL: ROUTE_HEADSET =====
I/AudioHardwareLittleton( 44): ================= enable_hifi_headset ======================
I/state.c ( 44): load_state(): file =/etc/alsactl/asound.state_none, cardname=(null)
I/state.c ( 44): hd: load_state returns ok
I/AudioHardwareLittleton( 44): alsactl_lib_restore("/etc/alsactl/asound.state_none") returns 0
I/state.c ( 44): load_state(): file =/etc/alsactl/asound.state_headset_mp3, cardname=(null)
I/state.c ( 44): hd: load_state returns ok
I/AudioHardwareLittleton( 44): alsactl_lib_restore("/etc/alsactl/asound.state_headset_mp3") returns 0
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::disableAlsaDevice()*************************
**
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::enableAlsaDevice(hw:0,0,0) (hd want asla)**
*************************
I/AudioHardwareLittleton( 44): --------------- AudioStreamOutMarvell::set() -----------------
V/AudioHardwareLittleton( 44): rate eventually set as 48000
V/AudioHardwareLittleton( 44): buffer time eventually set as 682666 usec
V/AudioHardwareLittleton( 44): headset.state=256
period time eventually set as 10666 usec
keypad down
I/AudioHardwareLittleton( 44): ###### enableAlsaDevice: alsa should ok #########
I/AudioService( 80): AudioService.java: setRouting(): ---2--
D/PhoneApp( 127): MediaButtonBroadcastReceiver.onReceive()... event = KeyEvent{action=0 code=79 repeat=0 meta=0
scancode=200 mFlags=0}
D/PhoneApp( 127): MediaButtonBroadcastReceiver: HEADSETHOOK down!
D/PhoneUtils( 127): handleHeadsetHook()...
D/PhoneApp( 127): ==> handleHeadsetHook(): consumed = false
I/AudioManager( 80): +++++++++++++++++++ AudioManager.java: setRouting(): mode=1,routes=8,mask=-17
I/AudioManager( 80): AudioManager: setRouting...
I/AudioService( 80): AudioService.java: setRouting(): mode= 1, routes=8 ,mask=-17
I/AudioService( 80): AudioService.java: setRouting(): ---1--
I/AudioSystem( 80): hd: AudioSystem.cpp: here?
I/AudioSystem( 80): hd: AudioSystem.cpp: setRouting(1, 8, 4294967279)
I/AudioFlinger( 44): hd: AudioFlinger.cpp: setRouting(1, 8, 4294967279)
D/AudioFlinger( 44): hd: setRouting 1 8 -17, tid 72, calling tid 80
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::getRouting(1)***************************
I/AudioHardwareLittleton( 44): *************************AudioHardwareMarvell::setRouting(1,8)*******************
********
I/AudioService( 80): AudioService.java: setRouheadset.state=256
ting(): ---2--
I/AudioManager( 80): +++++++++keypad up
++++++++++ AudioManager.java: setRouting(): mode=2,routes=8,mask=-1
I/AudioManager( 80): AudioManager: setRouting...
I/AudioService( 80): AudioService.java: setRouting(): mode= 2, routes=8 ,mask=-1
I/AudioService( 80): AudioService.java: setRouting(): ---1--
I/AudioSystem( 80): hd: AudioSystem.cpp: here?
I/AudioSystem( 80): hd: AudioSystem.cpp: setRouting(2, 8, 4294967295)
I/AudioFlinger( 44): hd: AudioFlinger.cpp: setRouting(2, 8, 4294967295)
D/AudioFlinger( 44): hd: setRouting 2 8 -1, tid 66, calling tid 80
E/AudioFlinger( 44): mA2dpDisableCount is already zero
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::getRouting(2)***************************
I/AudioHardwareLittleton( 44): *************************AudioHardwareMarvell::setRouting(2,8)*******************
********
I/AudioService( 80): AudioService.java: setRouting(): ---2--
I/AudioManager( 80): +++++++++++++++++++ AudioManager.java: setRouting(): mode=3,routes=8,mask=-1
I/AudioManager( 80): AudioManager: setRouting...
I/AudioService( 80): AudioService.java: setRouting(): mode= 3, routes=8 ,mask=-1
I/AudioService( 80): AudioService.java: setRouting(): ---2--
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::getMode()***************************
V/OMXAudioNode( 44): HandleComponentStateChange: OMX State 3 reached
D/PhoneApp( 127): MediaButtonBroadcastReceiver.onReceive()... event = KeyEvent{action=1 code=79 repeat=0 meta=0
scancode=200 mFlags=0}
D/Lights ( 80): ---->calling set_light_attention(),line=114 state->color=-15724528
D/IconMerger( 80): IconMerger width icon_num346 5
==================
拔掉耳机
=======
.........gpio= 104
.........state= 0
V/HeadsetObserver( 80): Headset UEVENT: {SWITCheadset.state=0
H_STATE=0, SWITCH_NAME=h2w, ACTION=change, SEQNUheadset.state=0
M=804, DEVPATH=/class/switch/h2w, SUBSYSTEM=switch}
D/PhoneApp( 127): mReceiver: ACTION_HEADSET_PLUG
D/PhoneApp( 127): state: 0
D/PhoneApp( 127): name: h2w
D/PhoneUtils( 127): restoreSpeakerMode, restoring to: false
D/IconMerger( 80): IconMerger width icon_num378 5
D/StatusIconArray( 80): StatusIconArray width icon_num35 5
V/OMXAudioNode( 44): HandleComponentStateChange: OMX State 4 reached
D/IconMerger( 80): IconMerger width icon_num378 5
headset.state=0
headset.state=0
I/AudioManager( 80): +++++++++++++++++++ AudioManager.java: setRouting(): mode=0,routes=2,mask=-17
I/AudioManager( 80): AudioManager: setRouting...
I/AudioService( 80): AudioService.java: setRouting(): mode= 0, routes=2 ,mask=-17
I/AudioService( 80): AudioService.java: setRouting(): ---1--
I/AudioSystem( 80): hd: AudioSystem.cpp: here?
I/AudioSystem( 80): hd: AudioSystem.cpp: setRouting(0, 2, 4294967279)
I/AudioFlinger( 44): hd: AudioFlinger.cpp: setRouting(0, 2, 4294967279)
D/AudioFlinger( 44): hd: setRouting 0 2 -17, tid 64, calling tid 80
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::getRouting(0)***************************
I/AudioHardwareLittleton( 44): *************************AudioHardwareMarvell::setRouting(0,2)*******************
********
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::doRouting(0, 8, 0, 2)***********************
****
I/AudioHardwareLittleton( 44): #################################
I/AudioHardwareLittleton( 44): ######### doRouting ###########
I/AudioHardwareLittleton( 44): #################################
I/AudioHardwareLittleton( 44): ===== Audio Path: MODE_NORMAL: ROUTE_SPEAKER =====
I/AudioHardwareLittleton( 44): =================== enable_hifi_mono ===========================
I/state.c ( 44): load_state(): file =/etc/alsactl/asound.state_none, cardname=(null)
I/state.c ( 44): hd: load_state returns ok
I/AudioHardwareLittleton( 44): alsactl_lib_restore("/etc/alsactl/asound.state_none") returns 0
I/state.c ( 44): load_state(): file =/etc/alsactl/asound.state_speaker_mp3, cardname=(null)
I/state.c ( 44): hd: load_state returns ok
I/AudioHardwareLittleton( 44): alsactl_lib_restore("/etc/alsactl/asound.state_speaker_mp3") returns 0
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::disableAlsaDevice()*************************
**
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::enableAlsaDevice(hw:0,0,0) (hd want asla)**
*************************
I/AudioHardwareLittleton( 44): --------------- AudioStreamOutMarvell::set() -----------------
V/AudioHardwareLittleton( 44): rate eventually set as 48000
V/AudioHardwareLittleton( 44): buffer time eventually set as 682666 usec
V/AudioHardwareLittleton( 44): period time eventually set as 10666 usec
I/AudioHardwareLittleton( 44): ###### enableAlsaDevice: alsa should ok #########
I/AudioService( 80): AudioService.java: setRouting(): ---2--
I/AudioManager( 80): +++++++++++++++++++ AudioManager.java: setRouting(): mode=1,routes=2,mask=-17
I/AudioManager( 80): AudioManager: setRouting...
I/AudioService( 80): AudioService.java: setRouting(): mode= 1, routes=2 ,mask=-17
I/AudioService( 80): AudioService.java: setRouting(): ---1--
I/AudioSystem( 80): hd: AudioSystem.cpp: here?
I/AudioSystem( 80): hd: AudioSystem.cpp: setRouting(1, 2, 4294967279)
I/AudioFlinger( 44): hd: AudioFlinger.cpp: setRouting(1, 2, 4294967279)
D/AudioFlinger( 44): hd: setRouting 1 2 -17, tid 72, calling tid 80
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::getRouting(1)***************************
I/AudioHardwareLittleton( 44): *************************AudioHardwareMarvell::setRouting(1,2)*******************
********
I/AudioService( 80): AudioService.java: setRouting(): ---2--
I/AudioManager( 80): +++++++++++++++++++ AudioManager.java: setRouting(): mode=2,routes=1,mask=-1
I/AudioManager( 80): AudioManager: setRouting...
I/AudioService( 80): AudioService.java: setRouting(): mode= 2, routes=1 ,mask=-1
I/AudioService( 80): AudioService.java: setRouting(): ---1--
I/AudioSystem( 80): hd: AudioSystem.cpp: here?
I/AudioSystem( 80): hd: AudioSystem.cpp: setRouting(2, 1, 4294967295)
I/AudioFlinger( 44): hd: AudioFlinger.cpp: setRouting(2, 1, 4294967295)
D/AudioFlinger( 44): hd: setRouting 2 1 -1, tid 69, calling tid 80
E/AudioFlinger( 44): mA2dpDisableCount is already zero
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::getRouting(2)***************************
I/AudioHardwareLittleton( 44): *************************AudioHardwareMarvell::setRouting(2,1)*******************
********
I/AudioService( 80): AudioService.java: setRouting(): ---2--
I/AudioManager( 80): +++++++++++++++++++ AudioManager.java: setRouting(): mode=3,routes=8,mask=-1
I/AudioManager( 80): AudioManager: setRouting...
I/AudioService( 80): AudioService.java: setRouting(): mode= 3, routes=8 ,mask=-1
I/AudioService( 80): AudioService.java: setRouting(): ---2--
D/dalvikvm( 246): GC freed 755 objects / 129048 bytes in 213ms
========
 
拔掉耳机:
bash-3.2# I/WindowManager( 81): onOrientationChanged, rotation changed to 0
.........gpio= 104
.........state= 0
V/HeadsetObserver( 81): Headset UEVENT: {SWITCH_STATE=0, SWITCH_NAME=h2w, ACTION=change, SEQNUM=787, DEVPATH=/cl
ass/switch/h2w, SUBSYSTEM=switch}
D/PhoneApp( 124): mReceiver: ACTION_HEADSET_PLUG
D/PhoneApp( 124): state: 0
D/PhoneApp( 124): name: h2w
D/PhoneUtils( 124): restoreSpeakerMode, restoring to: false
D/IconMerger( 81): IconMerger width icon_num378 5
D/StatusIconArray( 81): StatusIconArray width icon_num35 5
headset.state=0
headset.state=0
I/ActivityManager( 81): Start proc com.android.music for broadcast com.android.music/.MediaButtonIntentReceiver:
pid=238 uid=10011 gids={3003}
headset.state=0
headset.state=0
headset.state=0
headset.state=0
V/OMXAudioNode( 44): Got Component OMX.MARVELL.AUDIO.MP3DECODER handle
V/OMXAudioNode( 44): NegotiateComponentParameters: Inport buffers 5, size 4096
V/OMXAudioNode( 44): SamplesPerFrame 1152, Channels 2
V/OMXAudioNode( 44): NegotiateComponentParameters: Outport buffers 9, size 36864
V/OMXAudioNode( 44): HandleComponentStateChange: OMX State 2 reached
V/OMXAudioNode( 44): HandleComponentStateChange: OMX State 3 reached
V/OMXAudioNode( 44): OMX_PortSettingsChanged:Updated SR = 44100 CH = 2
D/MediaPlaybackService( 238): xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /sdcard/标准测试音频/White Denim - I Sta
rt To Run.mp3
V/OMXAudioNode( 44): HandleProcessingState: new output buffers 9, size 36864
I/AudioManager( 81): +++++++++++++++++++ AudioManager.java: setRouting(): mode=0,routes=2,mask=-17
I/AudioManager( 81): AudioManager: setRouting...
I/AudioService( 81): AudioService.java: setRouting(): mode= 0, routes=2 ,mask=-17
I/AudioService( 81): AudioService.java: setRouting(): ---1--
I/AudioSystem( 81): hd: AudioSystem.cpp: here?
I/AudioSystem( 81): hd: AudioSystem.cpp: setRouting(0, 2, 4294967279)
I/AudioFlinger( 44): hd: AudioFlinger.cpp: setRouting(0, 2, 4294967279)
D/AudioFlinger( 44): hd: setRouting 0 2 -17, tid 68, calling tid 81
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::getRouting(0)***************************
I/AudioHardwareLittleton( 44): *************************AudioHardwareMarvell::setRouting(0,2)*******************
********
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::doRouting(0, 8, 0, 2)***********************
****
I/AudioHardwareLittleton( 44): #################################
I/AudioHardwareLittleton( 44): ######### doRouting ###########
I/AudioHardwareLittleton( 44): #################################
I/AudioHardwareLittleton( 44): ===== Audio Path: MODE_NORMAL: ROUTE_SPEAKER =====
I/AudioHardwareLittleton( 44): =================== enable_hifi_mono ===========================
I/state.c ( 44): load_state(): file =/etc/alsactl/asound.state_none, cardname=(null)
I/state.c ( 44): hd: load_state returns ok
I/AudioHardwareLittleton( 44): alsactl_lib_restore("/etc/alsactl/asound.state_none") returns 0
I/state.c ( 44): load_state(): file =/etc/alsactl/asound.state_speaker_mp3, cardname=(null)
I/state.c ( 44): hd: load_state returns ok
I/AudioHardwareLittleton( 44): alsactl_lib_restore("/etc/alsactl/asound.state_speaker_mp3") returns 0
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::disableAlsaDevice()*************************
**
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::enableAlsaDevice(hw:0,0,0) (hd want asla)**
*************************
I/AudioHardwareLittleton( 44): --------------- AudioStreamOutMarvell::set() -----------------
V/AudioHardwareLittleton( 44): rate eventually set as 48000
V/AudioHardwareLittleton( 44): buffer time eventually set as 682666 usec
V/AudioHardwareLittleton( 44): period time eventually set as 10666 usec
I/AudioHardwareLittleton( 44): ###### enableAlsaDevice: alsa should ok #########
I/AudioService( 81): AudioService.java: setRouting(): ---2--
I/AudioManager( 81): +++++++++++++++++++ AudioManager.java: setRouting(): mode=1,routes=2,mask=-17
I/AudioManager( 81): AudioManager: setRouting...
I/AudioService( 81): AudioService.java: setRouting(): mode= 1, routes=2 ,mask=-17
I/AudioService( 81): AudioService.java: setRouting(): ---1--
I/AudioSystem( 81): hd: AudioSystem.cpp: here?
I/AudioSystem( 81): hd: AudioSystem.cpp: setRouting(1, 2, 4294967279)
I/AudioFlinger( 44): hd: AudioFlinger.cpp: setRouting(1, 2, 4294967279)
D/AudioFlinger( 44): hd: setRouting 1 2 -17, tid 70, calling tid 81
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::getRouting(1)***************************
I/AudioHardwareLittleton( 44): *************************AudioHardwareMarvell::setRouting(1,2)*******************
********
I/AudioService( 81): AudioService.java: setRouting(): ---2--
I/AudioManager( 81): +++++++++++++++++++ AudioManager.java: setRouting(): mode=2,routes=1,mask=-1
I/AudioManager( 81): AudioManager: setRouting...
I/AudioService( 81): AudioService.java: setRouting(): mode= 2, routes=1 ,mask=-1
I/AudioService( 81): AudioService.java: setRouting(): ---1--
I/AudioSystem( 81): hd: AudioSystem.cpp: here?
I/AudioSystem( 81): hd: AudioSystem.cpp: setRouting(2, 1, 4294967295)
I/AudioFlinger( 44): hd: AudioFlinger.cpp: setRouting(2, 1, 4294967295)
D/AudioFlinger( 44): hd: setRouting 2 1 -1, tid 72, calling tid 81
E/AudioFlinger( 44): mA2dpDisableCount is already zero
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::getRouting(2)***************************
I/AudioHardwareLittleton( 44): *************************AudioHardwareMarvell::setRouting(2,1)*******************
********
I/AudioService( 81): AudioService.java: setRouting(): ---2--
I/AudioManager( 81): +++++++++++++++++++ AudioManager.java: setRouting(): mode=3,routes=8,mask=-1
I/AudioManager( 81): AudioManager: setRouting...
I/AudioService( 81): AudioService.java: setRouting(): mode= 3, routes=8 ,mask=-1
I/AudioService( 81): AudioService.java: setRouting(): ---2--
drivers/video/backlight/micco_bl.c(miccobl_send_intensity): send intensity is 5
drivers/video/backlight/micco_bl.c(miccobl_send_intensity): send intensity is 4
drivers/video/backlight/micco_bl.c(miccobl_send_intensity): send intensity is 3
drivers/video/backlight/micco_bl.c(miccobl_send_intensity): send intensity is 2
drivers/video/backlight/micco_bl.c(miccobl_send_intensity): send intensity is 1
 
 
播放列表开始播放音乐:
V/OMXAudioNode( 44): HandleComponentStateChange: OMX State 2 reached
V/OMXAudioNode( 44): HandleComponentStateChange: OMX State 1 reached
V/OMXAudioNode( 44): Got Component OMX.MARVELL.AUDIO.MP3DECODER handle
V/OMXAudioNode( 44): NegotiateComponentParameters: Inport buffers 5, size 4096
V/OMXAudioNode( 44): SamplesPerFrame 1152, Channels 2
V/OMXAudioNode( 44): NegotiateComponentParameters: Outport buffers 9, size 36864
V/OMXAudioNode( 44): HandleComponentStateChange: OMX State 2 reached
V/OMXAudioNode( 44): HandleComponentStateChange: OMX State 3 reached
V/OMXAudioNode( 44): OMX_PortSettingsChanged:Updated SR = 44100 CH = 2
D/MediaPlaybackService( 238): xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /sdcard/标准测试音频/White Denim - I Sta
rt To Run.mp3
I/AudioHardwareLittleton( 44): ***************AudioHardwareMarvell::getMode()***************************
V/OMXAudioNode( 44): HandleProcessingState: new output buffers 9, size 36864
I/ActivityManager( 81): Starting activity: Intent { action=com.android.music.PLAYBACK_VIEWER flags=0x4000000 com
p={com.android.music/com.android.music.MediaPlaybackActivity} }
D/IconMerger( 81): IconMerger width icon_num346 5
D/MediaPlaybackActivity( 238): ------------aduio-id = 5
D/MediaPlaybackActivity( 238): -----------queue--id = 4
D/MediaPlaybackActivity( 238): ---------------size = 13
D/MediaPlaybackActivity( 238): ---------------size = 13
I/ActivityManager( 81): Displayed activity com.android.music/.MediaPlaybackActivity: 674 ms
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bash-3.2# headset.state=0
headset.state=0
headset.state=0
headset.state=0
headset.state=0
headset.state=0
headset.state=0
.........gpio= 104
.........state= 256
headset.state=256
not headset keypad
headset.state=256
keypad down
headset.state=256
keypad up
 
==============
GPIO-80 autorequested
GPIO-81 autorequested
headset.state=256
not headset keypad
 
修改后的内核:
 
 
 
touchscreen irq (Gpio 118) is high level
 
 
 
 
 
 
===============================================================================================
输入输出子系统分析
Tty_io.c (d:\linux-2.6.25-littleton\drivers\char)
static int __init tty_init(void)
{
//
cdev_init(&tty_cdev, &tty_fops);
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n");
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), "tty");
 
cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), "console");
 
#ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops);
if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n");
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), "ptmx");
#endif
//虚拟终端
#ifdef CONFIG_VT
cdev_init(&vc0_cdev, &console_fops);
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");
device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0");
 
vty_init();
#endif
return 0;
}
CONFIG_VT:是指配置虚拟终端.即我们所说的控制台.在此可以看到TTY_MAJOR(4),0对应的设备节点操作集为console_fops.
区分/dev/tty、/dev/console、/dev/pts、/dev/ttyn
tty设备
通常我们在linux下看到的控制台(console)是由几个设备完成的。分别是/dev/ttyN(其中tty0就是/dev/console,
tty1,tty2就是不同的虚拟终端(virtual console)).通常使用热键alt+Fn来在这些虚拟终端之间进行切换。所有
的这些tty设备都是由linux/drivers/char /console.c和vt.c对应。
4656 tty4 00:00:00 getty
4657 tty5 00:00:00 getty
4663 tty2 00:00:00 getty
4670 tty3 00:00:00 getty
4673 tty6 00:00:00 getty
24071 tty1 00:00:00 getty
6774 tty7 00:33:58 Xorg
 
ctrl+alt+F1 从tty1登录
4656 tty4 00:00:00 getty
4657 tty5 00:00:00 getty
4663 tty2 00:00:00 getty
4670 tty3 00:00:00 getty
4673 tty6 00:00:00 getty
6774 tty7 00:34:05 Xorg
24071 tty1 00:00:00 login
24145 tty1 00:00:00 bash
23525 pts/2 00:00:00 bash
24670 pts/2 00:00:00 ps
 
/dev/pts是远程登陆(telnet,ssh等)后创建的控制台设备文件所在的目录。由于可能有好几千个用户登陆,
所以/dev/pts其实是动态生成的,不象其他设备文件是构建系统时就已经产生的硬盘节点(如果未使用devfs)
第一个用户登陆,console的设备文件为/dev/pts/0,第二个为/dev/pts/1,以此类推。这里的0、1、2、
3不是具体的标准输入或输出,而是整个控制台。
打开 pts/0 和 pts/1 两个终端 ,如果在pts/0 里面执行:
echo aaa>/dev/pts/1 那么 aaa 将会在 pts/1 所在的终端里显示。
/dev/tty指的是当前所处的终端,输出到此的内容只会显示在当前工作的终端显示器上
/dev/console就是tty0
 
tty_init()
vty_init();
kbd_init();
 
 
Atkbd.c (d:\linux-2.6.25-littleton\drivers\input\keyboard)
static struct serio_driver atkbd_drv = {
.driver = {
.name = "atkbd",
},
.description = DRIVER_DESC,
.id_table = atkbd_serio_ids,
.interrupt = atkbd_interrupt,
.connect = atkbd_connect,
.reconnect = atkbd_reconnect,
.disconnect = atkbd_disconnect,
.cleanup = atkbd_cleanup,
};
 
Gpio_keys.c (d:\linux-2.6.25-littleton\drivers\input\keyboard): return platform_driver_register(&gpio_keys_device_driver);
Omap-keypad.c (d:\linux-2.6.25-littleton\drivers\input\keyboard): return platform_driver_register(&omap_kp_driver);
Pxa27x_keypad.c (d:\linux-2.6.25-littleton\drivers\input\keyboard): return platform_driver_register(&pxa27x_keypad_driver);
Pxa930_trkball.c (d:\linux-2.6.25-littleton\drivers\input\mouse): return platform_driver_register(&pxa930_trkball_driver);
I8042.c (d:\linux-2.6.25-littleton\drivers\input\serio): err = platform_driver_register(&i8042_driver);
Rpckbd.c (d:\linux-2.6.25-littleton\drivers\input\serio): return platform_driver_register(&rpckbd_driver);
Corgi_ts.c (d:\linux-2.6.25-littleton\drivers\input\touchscreen): return platform_driver_register(&corgits_driver);
Micco_touch.c (d:\linux-2.6.25-littleton\drivers\input\touchscreen): return platform_driver_register(&micco_ts_driver);
Wm9713_touch.c (d:\linux-2.6.25-littleton\drivers\input\touchscreen): return platform_driver_register(&wm9713_touch_driver);
 
 
 
Pxa27x_keypad.c (d:\linux-2.6.25-littleton\drivers\input\keyboard)
static struct platform_driver pxa27x_keypad_driver = {
.probe = pxa27x_keypad_probe,
.remove = __devexit_p(pxa27x_keypad_remove),
.suspend = pxa27x_keypad_suspend,
.resume = pxa27x_keypad_resume,
.driver = {
.name = "pxa27x-keypad",
},
};
 
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver;
};
 
 
struct device_driver {
const char *name;
struct bus_type *bus;
 
struct module *owner;
const char *mod_name; /* used for built-in modules */
 
int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
struct attribute_group **groups;
 
struct driver_private *p;
};
 
pxa27x_keypad_init()
return platform_driver_register(&pxa27x_keypad_driver);
//int platform_driver_register(struct platform_driver *drv) Platform.c (d:\linux-2.6.25-littleton\drivers\base)
drv->driver.bus = &platform_bus_type;
return driver_register(&drv->driver);
//Driver.c (d:\linux-2.6.25-littleton\drivers\base) int driver_register(struct device_driver *drv)
ret = bus_add_driver(drv);
//Bus.c (d:\linux-2.6.25-littleton\drivers\base):int bus_add_driver(struct device_driver *drv)
error = driver_attach(drv);
//Dd.c (d:\linux-2.6.25-littleton\drivers\base):int driver_attach(struct device_driver *drv)
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
//int bus_for_each_dev(struct bus_type *bus, struct device *start,void *data, int (*fn)(struct device *, void *))
struct device *dev;
error = fn(dev, data);
fn执行的是 static int __driver_attach(struct device *dev, void *data)
driver_probe_device(drv, dev);
ret = really_probe(dev, drv);
if (dev->bus->probe)
{
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
}
else if (drv->probe)
{
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
driver_bound(dev);
 
此处 drv->probe 调用的是 platform_drv_probe
static int platform_drv_probe(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
 
return drv->probe(dev);
}
所以最终调用的是 pxa27x_keypad_probe
 
 
static int __init i8042_init(void)
err = platform_driver_register(&i8042_driver);
return driver_register(&drv->driver);
 
static int __devinit i8042_probe(struct platform_device *dev)
error = i8042_setup_kbd();
error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED,"i8042", i8042_platform_device);
中断函数:
static irqreturn_t i8042_interrupt(int irq, void *dev_id)
{
...
spin_lock_irqsave(&i8042_lock, flags);
str = i8042_read_status();
...
//在这里serio_interrupt被调用,进而调用struct serio_driver atkbd_drv中的atkbd_interrupt
if (likely(port->exists))
serio_interrupt(port->serio, data, dfl);
 
out:
return IRQ_RETVAL(ret);
}
serio_interrupt被调用,进而调用struct serio_driver atkbd_drv中的atkbd_interrupt
 
static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,unsigned int flags)
{
struct atkbd *atkbd = serio_get_drvdata(serio);
struct input_dev *dev = atkbd->dev;
...
input_event(dev, EV_KEY, keycode, value);
...
input_report_key(dev, BTN_MIDDLE, click);
...
}
static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_KEY, code, !!value);
}
 
static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED,pdev->name, keypad);
中断函数:
static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
{
struct pxa27x_keypad *keypad = dev_id;
unsigned long kpc = keypad_readl(KPC);
if (kpc & KPC_DI)
pxa27x_keypad_scan_direct(keypad);
input_report_key(keypad->input_dev,...);
if (kpc & KPC_MI)
pxa27x_keypad_scan_matrix(keypad);
return IRQ_HANDLED;
}
 
#define KPC 0x0000 /* Keypad Control register */
unsigned long kpc = keypad_readl(KPC);
读取 Keypad Control register 寄存器的内容
#define KPC_DI (0x1 << 5) /* Direct key interrupt bit */
#define KPC_MI (0x1 << 22) /* Matrix interrupt bit */
 
 
pxa27x_keypad_scan_matrix()
input_report_key(keypad->input_dev,lookup_matrix_keycode(keypad, row, col),new_state[col] & (1 << row));
lookup_matrix_keycode()
return keypad->matrix_keycodes[(row << 3) + col];
static inline unsigned int lookup_matrix_keycode(struct pxa27x_keypad *keypad, int row, int col)
 
static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
keypad->matrix_keycodes[(row << 3) + col] = code;
 
 
 
static int kbd_connect(struct input_handler *handler, struct input_dev *dev,const struct input_device_id *id)
{
struct input_handle *handle;
...
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
...
handle->dev = dev;
handle->handler = handler;
handle->name = "kbd";
error = input_register_handle(handle);
...
}
 
 
 
input_register_handler 和 input_register_device 分别将:
将一个input_handler结构题 注册到输入子系统的 input_handler_list 链表中
将一个input_dev 结构题 注册到输入子系统的 input_dev_list 链表中
定义如下:
Input.c (d:\linux-2.6.25-littleton\drivers\input)
int input_register_handler(struct input_handler *handler)
{
struct input_dev *dev;
...
INIT_LIST_HEAD(&handler->h_list);
...
list_add_tail(&handler->node, &input_handler_list);
 
list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler);
...
}
Input.c (d:\linux-2.6.25-littleton\drivers\input)
int input_register_device(struct input_dev *dev)
{
static atomic_t input_no = ATOMIC_INIT(0);
struct input_handler *handler;
const char *path;
...
list_add_tail(&dev->node, &input_dev_list);
list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler);
...
}
他们都使用了一个比较重要的函数: input_attach_handler
定义在 Input.c (d:\linux-2.6.25-littleton\drivers\input):
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
const struct input_device_id *id;
int error;
//在这里匹配主要是调用 input_match_device来进行的,但是handler结构体里面还有个"黑名单"字段,意思是说虽然咱俩认识,但是你在我的黑名单里,照样拜拜...
if (handler->blacklist && input_match_device(handler->blacklist, dev))
return -ENODEV;
//handler结构体里的id_table指针表明了可以与此驱动联姻的设备种类,根据这个字段我们调用这个函数
id = input_match_device(handler->id_table, dev);
if (!id)
return -ENODEV;
//这个函数如果返回不为空那么我们就为他们正式举行婚礼...而此时,我们调用的这个connect就是在keyboard.从中定义的那个handler结构体中的那个connect函数.是不是有点明白了?
error = handler->connect(handler, dev, id);
...
}
 
因为有 :
Mousedev.c (d:\linux-2.6.25-littleton\drivers\input): error = input_register_handler(&mousedev_handler);
static struct input_handler kbd_handler = {
.event = kbd_event,
.connect = kbd_connect,
.disconnect = kbd_disconnect,
.start = kbd_start,
.name = "kbd",
.id_table = kbd_ids,
};
int __init kbd_init(void)
{
...
error = input_register_handler(&kbd_handler);
...
}
对于 kbd_handler ,此时 input_attach_handler 中调用的 error = handler->connect(handler, dev, id) 实际上调用的是:
static int kbd_connect(struct input_handler *handler, struct input_dev *dev,const struct input_device_id *id)
{
struct input_handle *handle;
...
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
...
handle->dev = dev;
handle->handler = handler;
handle->name = "kbd";
error = input_register_handle(handle);
...
error = input_open_device(handle);
...
}
这里的 :
input_handle 与 input_handler
input_register_handle 与 input_register_handler 都比较像
struct input_handle 是用来连接struct input_handler和struct input_dev的结构,具体的连接
过程在函数:input_open_device 中实现。
int input_register_handle(struct input_handle *handle)
{
struct input_handler *handler = handle->handler;
//将此结构放入相应的handler和dev的h_list链表末尾
//一个handle结构对应一个handler,而一个handler不一定对应一个handle
list_add_tail(&handle->d_node, &handle->dev->h_list);
list_add_tail(&handle->h_node, &handler->h_list);
//这里还要检查下start函数,不为空在这里要被调用
if (handler->start)
handler->start(handle);
return 0;
}
在这个函数里所做的处理其实很简单.将handle挂到所对应input device的h_list链表上.还将handle挂到对应的handler的
hlist链表上.如果handler定义了start函数,将调用之。
对于 kbd_handler ,此时调用的start是:
Keyboard.c (d:\linux-2.6.25-littleton\drivers\char) 中的:
static void kbd_start(struct input_handle *handle)
{
unsigned char leds = ledstate;
 
tasklet_disable(&keyboard_tasklet);
if (leds != 0xff) {
input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
}
tasklet_enable(&keyboard_tasklet);
}
 
 
Atkbd.c (d:\linux-2.6.25-littleton\drivers\input\keyboard)
static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
struct atkbd *atkbd;
struct input_dev *dev;
atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
dev = input_allocate_device();
...
atkbd->dev = dev;
...
atkbd_set_device_attrs(atkbd);
struct input_dev *input_dev = atkbd->dev;
...
input_dev->name = atkbd->name;
...
input_dev->id.bustype = BUS_I8042;
...
input_dev->event = atkbd_event;
input_dev->dev.parent = &atkbd->ps2dev.serio->dev;
...
err = input_register_device(atkbd->dev);
 
 
Wm9713_touch.c (d:\linux-2.6.25-littleton\drivers\input\touchscreen):
static int ts_init(struct platform_device *pdev)
ret = input_register_device(codec_ts_input);
 
Pxa27x_keypad.c (d:\linux-2.6.25-littleton\drivers\input\keyboard)
static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
error = input_register_device(input_dev);
 
input_report_key 最终调用的是:input_event
input_event定义在:Input.c (d:\linux-2.6.25-littleton\drivers\input)
void input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
input_handle_event(dev, type, code, value);
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
dev->event(dev, type, code, value);
if (disposition & INPUT_PASS_TO_HANDLERS)
input_pass_event(dev, type, code, value);
rcu_read_lock();
handle = rcu_dereference(dev->grab);
if (handle)
handle->handler->event(handle, type, code, value);
else
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
if (handle->open)
handle->handler->event(handle,type, code, value);
rcu_read_unlock();
 
 
首先根据不同的事件,对设备的事件对应的位进行检查并设置.对于我们的键盘可以看到,如果按键对应的位没有置位,我们就不予理睬.
最后会调用handle->handler->event(handle, type, code, value).
因为有:
static struct input_handler kbd_handler = {
.event = kbd_event,
.connect = kbd_connect,
.disconnect = kbd_disconnect,
.start = kbd_start,
.name = "kbd",
.id_table = kbd_ids,
};
我们可以确定 handle->handler->event 调用的是 kbd_handler里面的 kbd_event
static void kbd_event(struct input_handle *handle, unsigned int event_type,
unsigned int event_code, int value)
{
if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
kbd_rawcode(value);
if (event_type == EV_KEY)
kbd_keycode(event_code, value, HW_RAW(handle->dev));
tasklet_schedule(&keyboard_tasklet);
do_poke_blanked_console = 1;
schedule_console_callback();
}
 
 
 
对于android系统,
WindowManagerService类的构造函数
WindowManagerService()
mQueue = new KeyQ();
因为 WindowManagerService.java (frameworks\base\services\java\com\android\server)中有:
private class KeyQ extends KeyInputQueue
KeyQ 是抽象类 KeyInputQueue 的实现,所以 new KeyQ类的时候实际上在 KeyInputQueue 类中创建了
一个线程 InputDeviceReader 专门用来冲设备读取按键事件,代码:
Thread mThread = new Thread("InputDeviceReader") {
public void run()
{
在循环中调用:readEvent(ev);
...
send = preprocessEvent(di, ev);
实际调用的是 KeyQ 类的 preprocessEvent 函数
...
int keycode = rotateKeyCodeLocked(ev.keycode);
int[] map = mKeyRotationMap;
for (int i=0; i<N; i+=2)
{
if (map[i] == keyCode)
return map[i+1];
} //
addLocked(di, curTime, ev.flags,RawInputEvent.CLASS_KEYBOARD,newKeyEvent(di, di.mDownTime, curTime, down,keycode, 0, scancode,...));
QueuedEvent ev = obtainLocked(device, when, flags, classType, event);
}
}
 
Linux设备模型之input子系统详解
http://blog.chinaunix.net/u1/51562/showart_1090628.html
浅析linux下键盘设备工作和注册流程
http://blog.chinaunix.net/u1/38994/showart_1130025.html
 
 
 
 
 
 
 
 
 
 
./temp_log.txt:2544:adb 调试 windows 下usb驱动
./temp_log.txt:2802:Max8660.c 是美信电源管理ic的驱动。
./temp_log.txt:2803:Micco.c 是 Dialog DA9034 驱动(linux)。marvell pxa3xx 最常用电源管理芯片
 
./temp_log.txt:4206: //handler结构体里的id_table指针表明了可以与此驱动联姻的设备种类,根据这个字段我们调用这个函数
./temp_log.txt:4997:Android GSM驱动模块详细分析 - 技术开发 | IT168
 
./temp_log.txt:5335:摄像头驱动相关
./temp_log.txt:6556:
 
 
 
 
 
./logcat.txt:180://针对marvell的 wpa 驱动
./logcat.txt:252:我们可以看出,目前 wpa_supplicant 只支持编译上了支持 Marvell 的 wpa_supplicant 驱动。
./linjinzhao.txt:287:直接make android源码时,并没有make linux kernel。因此是在运行模拟器,所以不用编译 linux kernel。如果要移值android,或增删驱动,则需要编译 linux kernel
./android/system/info_of_make_littleton.log:9:3. 编译驱动模块
./android/system/info_of_make_littleton.log:374:2.1.4 mtk 开机键驱动
./android/system/info_of_make_littleton.log:376:2.1.6 摄像头驱动
./android/system/info_of_make_littleton.log:377:2.1.7 usb驱动
 
./android/system/info_of_make_littleton.log:402:3. 编译驱动模块
./android/system/info_of_make_littleton.log:496:2.1.4 mtk 开机键驱动
./android/system/info_of_make_littleton.log:588:2009年06月03日 添加mtk开机键驱动 刘长健
./android/system/info_of_make_littleton.log:596:2.1.6 摄像头驱动
./android/system/info_of_make_littleton.log:609:驱动注册:
./android/system/info_of_make_littleton.log:613:2.1.7 usb驱动
 
./android/system/info_of_make_littleton.log:632:i2s cs42l51 驱动分析
./android/system/info_of_make_littleton.log:638:RTC设备驱动
./android/system/info_of_make_littleton.log:758:3. 编译驱动模块
./android/system/info_of_make_littleton.log:972:Linux I2C设备驱动--数据结构及驱动函数
./android/system/info_of_make_littleton.log:978:注册pci设备驱动 mrvlsdio
./android/system/info_of_make_littleton.log:1917:驱动相关
./android/system/info_of_make_littleton.log:1968:移植网卡驱动和lcd驱动到
./android/system/info_of_make_littleton.log:1980:替换网卡驱动
 
./android/system/init-rild.txt:495:1> 装载 wifi 驱动: WifiNative.loadDriver()
./android/system/init-rild.txt:499:2> 卸载 wifi 驱动: WifiNative.unloadDriver()
./android/system/analysis-boot.txt:343:因为没有电池驱动,导致系统认为低电而关机。
./android/system/analysis-wifi.txt:273:WifiNative.loadDriver() 装载 wifi驱动
./android/system/analysis-wifi.txt:339:驱动相关:
./android/system/analysis-wifi.txt:365:开源sdio stack 驱动
./android/system/analysis-wifi.txt:366:目前sourceforge网站上提供了Linux 2.6.18版本内核的sdiostack补丁,使用此补丁后可以编译出供Atheros SDIO wifi v1.0模块使用的驱动
./android/system/analysis-wifi.txt:367:注意:编译sdiostack驱动时使用的内核版本需要和目标平台上的内核版本一致,如果不是2.6.18版本的内核,在打补丁过程中可能会有提示信息,可以根据提示信息手工修改。不同平台的内核配置选项也会有所不同,可能需要对配置做少许调整。一般来说,补丁中包含的hcd模块代码不能满足需要,所以要想最终能使用SDIO WIFI网卡,最困难的地方在于如何获取缺少的这一部分的代码。MontaVista也提供了一个补丁下载,我没有用过这个补丁,但是其中包含的sdiostack文档是很好的资料。如果希望使用Atheros SDIO wifi v2.0,可以看看openmoko补丁。下一步,我将尝试编译wifi v2.0的驱动。
./android/driver/blob.txt:144:因为驱动注册为:
./android/svn.txt:219:tangligang 对 wifi 蓝牙 驱动模块进行了更新 ,具体更新见文档 change.log ReadMe
./android/svn.txt:310:1> lcd ,触摸屏,键盘 驱动
./android/svn.txt:312:3> 摄像头驱动
./android/svn.txt:316:6> wifi 驱动
./android/svn.txt:317:7> 蓝牙驱动
./android/svn.txt:323:1> lcd ,触摸屏,键盘 驱动
./android/svn.txt:324:1. 添加mtk开机键驱动
./android/svn.txt:333:添加了 max8660 电池驱动,去掉了 micco and avara 驱动,去掉了 osram sfh7225 驱动
./android/svn.txt:363:3> 摄像头驱动
./android/svn.txt:402:5> wifi 驱动
./android/svn.txt:417:7> 蓝牙驱动
./android/svn.txt:456:bmm 驱动 和 库源代码 :
./android/svn.txt:460:内核驱动模块
./android/app/settings/wifi.txt:74:WifiNative.loadDriver() 装载 wifi驱动
./android/app/settings/Wireless-controls.txt:44:1> 装载 wifi 驱动: WifiNative.loadDriver()
./android/app/settings/Wireless-controls.txt:48:2> 卸载 wifi 驱动: WifiNative.unloadDriver()
./android/app/settings/Wireless-controls.txt:176:1> 装载 wifi 驱动: WifiNative.loadDriver()
./android/app/settings/Wireless-controls.txt:180:2> 卸载 wifi 驱动: WifiNative.unloadDriver()
./android/app/settings/Security-location.txt:395:Android GSM驱动模块详细分析
./android/build-env.txt:198:另外GoldFish平台相关的驱动文件如下:
 
./binder.txt:25:服务管理程序首先打开 "/dev/binder" 驱动,然后调用 BINDER_SET_CONTEXT_MGR ioctl操作让binder内核驱动知道它是
./binder.txt:77://Android是支持Binder驱动的所以程序会调用getStrongProxyForHandle。这里handle为0,正好与Service_manager中的BINDER_SERVICE_MANAGER一致。
./binder.txt:80:ProcessState::self得到ProcessState实例。ProcessState将打开Binder驱动。一个进程仅只有一个 ProcessState实例。
./binder.txt:81:ProcessState 将打开"/dev/binder"驱动给 IPCThreadState使用。
./binder.txt:93:Android是支持Binder驱动的所以程序会调用getStrongProxyForHandle。这里handle为0,正好与Service_manager中的BINDER_SERVICE_MANAGER一致。
 
 

你可能感兴趣的:(linux,struct,Class,input,audio,keyboard)