精华内容
参与话题
问答
  • 如果您遇到了计算机故障,则可能是硬件驱动程序造成的。 这些是计算机操作系统用来与其硬件对话的软件。 从Windows到Android的每个操作系统都使用硬件驱动程序。 驱动程序就像计算机的翻译器 从根本上讲,两个主要...

    如果您遇到了计算机故障,则可能是硬件驱动程序造成的。 这些是计算机操作系统用来与其硬件对话的软件。 从Windows到Android的每个操作系统都使用硬件驱动程序。

    驱动程序就像计算机的翻译器

    从根本上讲,两个主要组件构成一台计算机-软件和硬件。 软件是您的操作系统(OS)以及已安装在其上的所有程序和应用程序。 主板,RAM,鼠标,键盘,打印机以及连接到计算机的其他任何物理设备组成了硬件。

    没有任何帮助,该软件将不会与您的硬件对话,反之亦然。 硬件驱动程序是一些软件,可以教您的OS,程序和应用程序如何与设备一起使用。 想象一下,您的操作系统说英语,而硬件说德语。 然后,硬件驱动程序是语言解释器,将英语转换为德语,然后再次转换为德语。

    制造商制造驱动; 软件开发人员使用它们
    由于驱动程序处理硬件翻译,您可能会认为这意味着制造硬件的制造商会制造驱动程序。 有时候是这样; 例如,制造商可能会制造您的图形驱动程序。 但这并非总是如此。

    Microsoft(和某些制造商)提供任何人都可以使用的通用驱动程序。 这些驱动程序可节省成本,并在整个设备上实现性能一致性。 跳过驱动程序创建过程,使制造商可以将其硬件调整为符合公司需求的,经过全面测试的著名驱动程序。 例如,您的鼠标,键盘和USB驱动器可能使

    用Microsoft制造的通用驱动程序。

    某些设备可以使用通用驱动程序,但在特定于设备的驱动程序下可能会表现更好。 例如,您的计算机的图形卡(GPU)可以使用通用驱动程序将您的桌面输出到显示器,但是为了获得最佳3D游戏性能,它需要其制造商NVIDIA,AMD或Intel的驱动程序。

    无论由谁来制作驱动程序,软件开发人员都可以利用和使用它们。 您的文本编辑器或文字处理器会调用打印驱动程序来与打印机一起使用,并调用图形驱动程序来显示文本。 没有这些驱动程序,您的程序将不知道如何与打印机或显示器对话以完成诸如打印和更改字体大小之类的基本功能。 硬件驱动程序可以使软件开发人员有所收获。 他们无需学习硬件语言的来龙去脉即可使用硬件。

    更多内容,参阅http://viadean.com

    展开全文
  • 通过硬件ID下载驱动

    2011-06-14 11:19:35
    通过硬件ID下载驱动通过硬件ID下载驱动
  • 作为一名入世未深的程序员,一直很好奇编写的一行行代码是如何实现对电脑硬件驱动,明明一个感觉是虚拟的东西,而另一个是实实在在的存在,观念上感觉压根就不是一个时空的东西,他们却偏偏能产生关系,并且能如此...
    作为一名入世未深的程序员,一直很好奇编写的一行行代码是如何实现对电脑硬件的驱动,明明一个感觉是虚拟的东西,而另一个是实实在在的存在,观念上感觉压根就不是一个时空的东西,他们却偏偏能产生关系,并且能如此协调的工作着,于是便搜索相关信息,看到了比较好的解释,就借来补充一下知识面~

    我们不妨从最底层开始往上走。

    1. 二进制理论

    众所周知,电脑,手机以及其他大量的电子设备,都是基于复杂的数字电路进行工作的。而数字电路则通过循环往复地完成一系列的指令,来输出我们想要的结果。

    那究竟里面的工作原理是什么样子的呢?

    首先,我们需要一套数字理论。

    上帝说,我们需要一个理论。于是莱布尼茨诞生了。
    莱布尼茨提出了二进制,这成为了现代计算机理论的基础。至于是老子启发了他,还是他自己坐而悟道想出了二进制,其实已经不重要了。有了二进制,一切变得简单起来:

    我们可以只用1 和0 来代表所有数字,进行和十进制一样的代数运算。虽然对于人脑来说,二进制非常不雅观, 比如:

    10001010101010101010 * 0101001101010 = 0101101001000001010011100110100。

    但它对于计算机来说, 则最简洁,最直观,最高效。 

    1.1 二进制运算

    每一位都只可能是1或者0,运算符号也就是加减乘除。虽然长,位数多,但速度极快!因为,但就每一位来说,运算之后,只会有几种情况:
    1 + 1 -> 0, 进一位(, 这个)
    1 + 0 -> 1.
    0 + 1 -> 1.
    0 + 0 -> 0.

    所以说,《三体》中,刘慈欣讲到人肉计算机一说。单个运算单元只需要记住特定指令相对应的操作即可,甚至连加减乘除都不需要会。 但这个在现实里面并不可能完成。假设这个运算恒纪元的程序有10000条指令(但显然这个条件都不成立,因为这个程序必然很复杂,涉及复杂的浮点运算和逻辑算法,甚至还有平方开放积分微分,10000条机器代码都不够塞牙缝的), 每条指令需要100个逻辑单元,每个单元的运算时间1秒钟,那么整个程序就需要1000000s (11天13小时46分钟)。。。所以可能程序还没算完,乱纪元又来了,所有人来不及脱水都死了。这还不算发盒饭,上厕所时间。

    1.2 二进制逻辑

    而且,电脑可以理解是非对错了。计算机以1表示“对”,“是”,“正确”。以0表示“错”,‘否’,‘错误’。然后又引进了“或”,‘与’,‘否定’,等逻辑语句。

    我们用 || 表示“或”,表示两者有一个成立即成立(我是学工科的(1) || 我是学计算机的(0) = 我没有女朋友(1))。
    0 || 0 = 0 
    0 || 1 = 1 
    1 || 0 = 1 
    1 || 1 = 1 
    我们用&& 表示“与”,表示两者都成立方可成立。(我是学工科的(1)&& 我是男的(1) = 我没有女朋友(1))。
    0 && 0 = 0 
    0 && 1 = 0 
    1 && 0 = 0 
    1 && 1 = 1 

    2. 数字电路的实现

    2.1. 逻辑门
    我们有了数字理论,那怎么才能做出逻辑电路呢?怎么才能用来运算呢?我们引入这些理想的逻辑门,靠他们来作运算。
    <img src="https://pic2.zhimg.com/97fa8547f049daa6342ffd2028928ca1_b.jpg" data-rawwidth="341" data-rawheight="221" class="content_image" width="341">
    这个就是与门,除非两个输入都是1,则输出1, 否则输出0.


    <img src="https://pic2.zhimg.com/e6573402f2cb3176e9ef159e044c9b79_b.jpg" data-rawwidth="285" data-rawheight="157" class="content_image" width="285">
    这个就是或门,除非两个输入都是0,则输出0,否则输出1.



    <img src="https://pic1.zhimg.com/53d94fa755fbed4f80f8d4aad4819f30_b.jpg" data-rawwidth="333" data-rawheight="238" class="content_image" width="333">

    这个就是非门,它会对输入取反(1变0,0变1 )


    <img src="https://pic2.zhimg.com/bbf9b74960381ab7d175c96333ab9c55_b.jpg" data-rawwidth="374" data-rawheight="135" class="content_image" width="374">这个叫或非电路,除非两输入相同则输出0,否则输出1这个叫或非电路,除非两输入相同则输出0,否则输出1

    现在,仅用一个理想原件,就可以做一次逻辑运算了!

    那如何做代数运算?比如加法?
    <img src="https://pic4.zhimg.com/b77ceb22b8f57d384112809914dd29ab_b.jpg" data-rawwidth="484" data-rawheight="278" class="origin_image zh-lightbox-thumb" width="484" data-original="https://pic4.zhimg.com/b77ceb22b8f57d384112809914dd29ab_r.jpg">以上的电路就能完成2以内的加法了。以上的电路就能完成2以内的加法了。
    当两个输入都是0, 高位输出0, 低位也是0 =》 0
    当两个输入都是1, 高位输出1, 低位也是0 =》 2
    当输入一个0一个1,高位输出0, 低位也是1 =》 1

    所以,大家也看到了,这个逻辑电路其实并不明白加法,它只是照部就搬的给我们了碰巧正确的结果——这就是我们常说的‘中文房间’的思想实验。

    我们有了2以内的加法,那么4以内也好解决了,8,16。。。以此类推,我们只要把数字电路互相叠加,就能得到很多功能,比如说加减乘除,求余等等数学运算,相应地,逻辑电路也会越来越复杂:
    <img src="https://pic4.zhimg.com/4009eac737796376f4d93af69ec4eaff_b.jpg" data-rawwidth="1440" data-rawheight="544" class="origin_image zh-lightbox-thumb" width="1440" data-original="https://pic4.zhimg.com/4009eac737796376f4d93af69ec4eaff_r.jpg">
    我们现在有了CPU,他可以完成简单的运算,但是这还不够。

    我们要编程。

    2.2. 编程
    程序本身就是指令的集合。

    所谓的编程就是将程序员所要实现的效果,用系统支持的指令写下来。就好比给你一本唐诗三百首,让你用里面的诗句组合(杂烩)成你想要表达的意思。

    当我们安装一个程序的时候,它本身实在硬盘里面的。 只有当我们启动它的时候,系统才会到硬盘里,找到该程序,然后将其读取到内存中。

    将设我们还在使用一个几十年前的电脑,这个电脑每次操作只操作的数字只有八个0或者1,也就是我们常说的8位系统。这些指令被存放到内存里面之后,CPU又会把它当下要执行的那一句放到寄存器里面,然后执行这条指令。一条接一条,循环往复。

    假设我们有一个8位指令。CPU得到它之后,就会分析,这一个指令里面,哪一段是操作符,哪一段是数字。比如:0101 00 11,它会读前四位,发现是加法(我瞎编的),然后读5-6位发现是0,7-8位是3,所以输出3。

    CPU得到3之后,会把它放到寄存器里面,然后进行后续操作。

    当然看似简单,8位操作里面的数字电路也会是无比复杂了(这还只是几十年前的科技,如今intel 64位处理器的复杂程度可见一斑)。

    至此,我们已经可以编程了。我们的程序会是这样子。

    00101010
    10101010
    01001101
    01010010

    计算机诞生之初,程序的确是这样的。但假如让如今的程序员来干这种事情,肯定又得哭爹喊娘一顿了(误)。所以,后来,出现了汇编语言。比如:
    MOV R1, #0x1
    MOV R2, #0x1
    ADD R1, R2, R1
    这是ARM的汇编指令,读出来如下
    在寄存器R1里面装1,
    在寄存器R2里面装1,
    计算R1 + R2 并将值放到R1里面。

    这就是一个简单的加法程序了。

    但是呢,这种程序写起来还是很不舒服,效率极低。
    于是高级语言语言。
    int a1 = 1;
    int a2 = 2;
    a1 = a1 + a2;

    这是c语言里面的一个简单加法。这个程序被我写完之后,会被编译出来——也就是有一个c的编译器,将这个程序转换成01010101 这样的指令(往土了说,就是个翻译机,把人类语言翻译成1&0)。当我们运行这个程序的时候,电脑会把这些东西放到内存里面,然后逐行的读取,然后一行行的运算。

    好了,我们可以回归问题了。

    3. CPU 对硬件的控制

    3.1. 对CPU的误解

    在我学习这些东西之前,我对CPU有一种误解。我以为在电脑里面,只有CPU是活的。换句话说,整个电脑里面,事无巨细,都是CPU一手操办的,就像一个勤奋的全栈工程师一样。

    其实,CPU更像是个产品经理。

    举个例子,我们的电脑里面有蓝牙。蓝牙里面其实也有一个CPU,更确切的说,是个MCU(Micro Control Unit),它负责将无线蓝牙信号解码成数字信号等一系列的操作,而CPU得工作只是协调MCU做相应的工作而已。

    给个场景:你打开了听歌软件,输出设备是蓝牙耳机。
    软件:哥,给我个耳机呗。
    CPU:大妹子,耳机没插,倒是有个蓝牙耳机。
    软件:那哥,你告诉蓝牙,俺要在他那里唱歌呗。
    CPU:欧了。
    CPU转向蓝牙。
    CPU:嘿,那个傻大个,说你呢,瞅啥,俺大妹子要你给她干个活。
    蓝牙:哥,你等会儿。
    蓝牙:scanning devices.....
    蓝牙:searching for possible peripherals providing required service.....
    蓝牙:device BLEX00010EFD010 discovered.....
    CPU: 啥玩样儿啊,让你干点事儿,咋这么墨迹呢?
    蓝牙:哥,这事儿费神,您和大妹子多担待啊。
    蓝牙:bonding with BLEX00010EFD010.
    蓝牙:bonding succeeded.
    蓝牙:Bluetooth Service Linkage Established.
    蓝牙:哥,成了,叫大妹子开始吧。
    CPU:真墨迹。
    CPU转向音乐软件。
    CPU:大妹子,开始吧。
    软件:哥,叫他唱“我是女生,可爱的女生”。
    CPU:转向蓝牙。
    CPU:傻大个,唱,“我是女生,可爱的女生”。
    蓝牙:check linkage lost?
    蓝牙:linkage quality good.
    蓝牙:signal to noise ratio: -20dB.
    蓝牙:transmission rate:1 Mb/s.
    蓝牙:我是女生,可爱的女生。。。。。

    所以,在这个实例里面,CPU只是充当了协调&领导的角色。所以一个程序得以实现,其实仰仗于CPU能顺畅,有效的发布指令,和得到结果。

    而这些信息的通道就叫 BUS,或者叫总线。

    3.2. 总线(BUS)
    就像上网用网线一样,电脑内部的通信也依赖于总线。这些总线传输数据,指令,地址等一系列的信息,是电脑完成各项计算和操作人物的物理基础。在计算机内部,每一个硬件设备都以特定的方式与CPU想连。哪怕是外接设备,也可以通过USB,SD卡槽得以连接。

    但单单有物理基础还是不够的,就像你只有电话线,只有网线,只有天线。

    你还需要一些通讯协议。

    4.3 通讯协议
    谁都有嘴,但并不是谁和谁都可以用嘴高效正确地传递信息。(我就发现,一和女孩子讲话,我就懵逼。) 而一门共同的语言就像是一个协议,确保双方所言所闻都能被正确的处理。总线也一样,也需要有一套既定的协议,得以让信息能在CPU和MCU之间正常往来。比较常用的协议有SPI, I2C, UART, 等等。这些协议规定了,什么指令表明什么含义,什么时候可以发信息,有几条数据线,电压多少,频率多少,等等。事无巨细,一律都有非常严谨统一的规定。

    为了不让看官厌烦,我也不会跟老学究老教授一样说一堆,如果后面有空间,我可以举几个例子,这边我暂且按下不表。

    4. 最终章:总结暨对这个问题的直接回复
    当程序员在电脑的终端写下一行命令,比如说"turn off the bulb"(我们假设有个程序员在CPU上接出一根电线到一个小灯泡上面) 。从打下到执行有如下步骤。

    我们的这句话会被编译成若干个指令,就像(瞎编):
    0101 0000(翻译:CPU把0写到内存里特定的位置),
    00010101(翻译:通过总线,用I2C,叫一下小灯泡的MCU),

    然后小灯泡被叫了一下之后,自己到约定的这个内存为止去读数字,发现是0,所以输出0,这个0 就是个低电压,可以理解成0V,然后0V和5V与逻辑之后,就是0V,所以小灯泡就关了。

    当然,我上面也纯属扯淡,这个指令不可能用短短几行代码来完成。使用I2C协议本身可能就需要超过一百条代码:通过吧某些地方的电压拉低,某些地方的电压拉高,来完成通信,有点类似黑帮片里面交易双方互相闪车灯。

    今天先写这些,后面有时间会再补充一些内容。

    看官们鼓励一下把。

    -------补充-------

    5. 逻辑门的物理实现:MOSFET

    有了理论上的逻辑门,现在需要做的,就是着手设计切实可用的逻辑元件。从最开始的阴极管到现在的晶体管(Transistors),在过去的大半个世纪,这些逻辑元件的实现经历了数次更新迭代。无论在速度,稳定性上,都出现了质的飞跃。 

    今天,我们就来讲一下MOSFET(metal–oxide–semiconductor field-effect transistor,金属氧化物场效应晶体管),它是现如今电子行业用的最多的逻辑元件,比如说我们常听到CMOS技术等等,就是基于MOSFET。

    但是,在开始之前,我们必须先涉猎枯燥的,玄幻的,又非常重要的半导体理论。

    5.1. 硅

    一切都要从硅开始说起。

    硅,其实并不稀奇。

    地球上最多的元素:氧硅铝铁。这个我们都会背。

    如果说没有贝尔实验室和那一群伯乐(我忘记那些科学家的名字了),可能硅还是会很平凡的,作为砂石,存在这个星球上。

    硅,基于我非常有限的高中化学知识:四价,共价键,非常稳定,不易得电子,不易失电子。

    除了稳定,看似没什么鸟用。但是,当少量的+3/+5价单质(如:Ga/As)被混入硅之后,我们就真的化腐朽为神奇了。

    比如说,假如我们把0.1 Mol的As混入了1 Mol的Si之后,因为As为+5价,所以相比于Si,那个多出来的电子非常活跃,容易脱离原子核。这就导致一块不带电的混合物里面,有大量的(这里,大量只是相对于一块Si单质)带正电的原子核(+5As丢了一个电子)和同等量的游离电子(e)。我们称这块混合半导体为n-type(negative)。

    到这里其实非常好理解。easy peasy。

    同理,我们可以想象把0.1 Mol的Ga混入另外一个1 Mol的Si里面。这时候,那些牛逼的理论物理学家在这时候引入了穴的概念(Holes)。因为Ga特别容易得电子,导致有些Si的电子会被Ga偷取,留下了一些穴,而这些穴,就像+1的电子,也会不停的运动。我们称这个半导体为p-type(positive)。

    然后,当我们把一个p-type 和一块n-type放在一起的时候,神奇到让人无法相信的事情发生了。

    (我觉得我可能都讲不清楚~~~~~~~)

    5.2. PN Junction(PN 结)

    我们可以自己做一下思想实验,接触面两边邻域的电子和穴会互相中和,导致这一块区域(depletion region)的电子和穴非常稀少,而那些固定的原子核(包括带+1的As和带-1的Ga)并不会变化。他们会造成一个稳定的电场,阻止了其他地方的电子和穴涌入。于是一个动态稳定(dynamic equilibrium)形成了,如图。
    <img src="https://pic4.zhimg.com/d31a4e375bf257d8b4dd1ac86ccc7f9b_b.png" data-rawwidth="661" data-rawheight="248" class="origin_image zh-lightbox-thumb" width="661" data-original="https://pic4.zhimg.com/d31a4e375bf257d8b4dd1ac86ccc7f9b_r.png">为了看官不头疼,这里我省去若干章节。总而言之,言而总之。到这里,我们就得到了一个二极管。为了看官不头疼,这里我省去若干章节。总而言之,言而总之。到这里,我们就得到了一个二极管。

    当我们施加一个正向电压的时候,depletion region会因为电压的缘故变薄,大量的电子和穴得以穿过,造成很强的电流。而当我们施加一个反向电压的时候,depletion region会变厚,电流无法通过。

    wah lah ~

    5.3. 场效应晶体管

    有了这个理论,后面要做的就不难了。(Bazinga!写到这里我已经彻底懵了,我是照着参考书写的。)

    一个MOSFET就长这样。
    <img src="https://pic3.zhimg.com/02821f8e167993b00416c3e8d85c925a_b.png" data-rawwidth="357" data-rawheight="342" class="content_image" width="357">为了便于理解它的工作原理,我们可以把它简化成这样:为了便于理解它的工作原理,我们可以把它简化成这样:
    <img src="https://pic2.zhimg.com/af795018c6c0530b8f771b34fb27584d_b.png" data-rawwidth="641" data-rawheight="473" class="origin_image zh-lightbox-thumb" width="641" data-original="https://pic2.zhimg.com/af795018c6c0530b8f771b34fb27584d_r.png">
    当我们不给Gate这个电压的时候,我们得到了两个典型的PN Junction(Drain & Subtract, Subtract & Source),电流是无法流过的。

    当我们给Gate施加一个正电压的时候,Gate的上层带正电,下层则带了负电。但因为Gate是个不导电的金属氧化物,所以它的下部会形成一个n type 通道(induced electron inversion layer)--电子可以直接从Source流到Drain。于是,我们得到了一个电流通路。

    这就是我们的逻辑开关了。

    最后,我们需要了解,MOSFET可以分为两种,一种叫P-MOS, 一种叫N-MOS。我们上面的图例其实是NMOS因为整个的载体为电子。很显然,PMOS的载体就是穴,它的source和drain都是P-type。

    在现实的使用中,两者的区别就是:
    High Gate Voltage Low Gate Voltage
    PMOS 断路 通路

    NMOS 通路 断路


    <img src="https://pic2.zhimg.com/712e825912f58a17cb441e2ea841714d_b.png" data-rawwidth="315" data-rawheight="167" class="content_image" width="315">
    5.4. CMOS (Complementary MOSFET BALABALA)逻辑电路

    单个的MOSFET似乎并没有神力,但当若干个mosfet组合到一起,我们就可以很轻松的得到各种我们想要的逻辑门。



    <img src="https://pic1.zhimg.com/e388f0e4f51b59e9698a1b42a68c0100_b.png" data-rawwidth="493" data-rawheight="420" class="origin_image zh-lightbox-thumb" width="493" data-original="https://pic1.zhimg.com/e388f0e4f51b59e9698a1b42a68c0100_r.png">

    这个图例看起来很复杂,但其实是个纸老虎。首先,我们给Vdd通5V电源。

    假设两个输入都是1, 即5V。对照5.3.的最后的表格
    Q1: 通
    Q2: 通
    Q3: 断
    Q4: 断 (Q1 和Q2 通导致Q5和Q6的Gate连到了5V,也即高电压上)
    Q5: 通
    Q6: 断
    所以,输出连接到了Vdd,也即5V,也即1.
    同理,其他易证。
    展开全文
  • 这篇文章在安卓7.1源码添加自己的硬件访问服务,从内核驱动,hal层,jni层,application framework,最后到app调用 包装类,在内核实现简单的打印输出,通过这篇文章,会让你对安卓整个的框架有深刻的认识。...

    序言:    

            这篇文章在安卓7.1源码添加自己的硬件访问服务,从内核驱动,hal层,jni层,application framework,最后到app调用    包装类,在内核实现简单的打印输出,通过这篇文章,会让你对安卓整个的框架有深刻的认识。

    本文为原创,转载请标明原址:https://blog.csdn.net/kai_zone/article/details/81305222

    系列文章:  Android硬件服务框架实例之Vibrator(驱动到应用)

                        安卓硬件访问服务框架

    为了便于理解,我们从底层到上层逐个添加和修改。

    1. 添加驱动,只实现一个简单的ioctl函数,驱动里打印app设置的值。

    led.c代码如下:

    ​
    ​
    #include <linux/device.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/fs.h>
    #include <linux/init.h>
    #include <linux/delay.h>
    #include <asm/uaccess.h>
    #include <asm/irq.h>
    #include <asm/io.h>
    static struct class *led_class;
    
    static int led_open(struct inode *inode, struct file *file)
    {
            printk(KERN_INFO "*******In  %s ***************\n", __func__);
            return 0;
    }
    static int led_release(struct inode *inodp, struct file *filp)
    {
            printk(KERN_INFO "*******In  %s ***************\n", __func__);
            return 0;
    }
    
    static long led_ioctl
    (struct file *filp, unsigned int status, unsigned long which)
    {
      printk("******(%s)status:%d;which:%d********\n", __func__,(int)status,(int)which);
      return 123;
    }
    
    static struct file_operations led_fops = {
        .owner  =   THIS_MODULE,    
        .open   =   led_open,
        .release = led_release,     
        .unlocked_ioctl = led_ioctl,
    };
    int major;
    static int led_init(void)
    {
            major = register_chrdev(0, "leds", &led_fops); 
            led_class = class_create(THIS_MODULE, "leddrv");
            device_create(led_class, NULL, MKDEV(major, 0), NULL, "led"); /*dev/led */
            return 0;
    }
    static void led_exit(void)
    {
            unregister_chrdev(major, "leds"); 
            device_destroy(led_class, MKDEV(major, 0));
            class_destroy(led_class);
    }
    
    module_init(led_init);
    module_exit(led_exit);
    MODULE_LICENSE("GPL");
    

    修改Makefile直接配置到内核,增加语句obj-y    +=    led.o。编译:make bootimage -j16烧写到开发板会生成/dev/led设备节点。

    2. hal层修改。

        (1). hardware/libhardware/modules/下新建目录led目录,在led目录下创建Android.mk和led_hal.c.

    Android.mk代码如下:

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := led.default
    
    # HAL module implementation stored in
    # hw/<LED_HARDWARE_MODULE_ID>.default.so
    LOCAL_MODULE_RELATIVE_PATH := hw
    LOCAL_C_INCLUDES := hardware/libhardware
    LOCAL_SRC_FILES := led_hal.c
    LOCAL_SHARED_LIBRARIES := liblog
    LOCAL_MODULE_TAGS := eng
    
    include $(BUILD_SHARED_LIBRARY)

    led_hal.c代码如下:

    ​
    #define LOG_TAG "LedHal"
    #include <hardware/vibrator.h>
    #include <hardware/hardware.h>
    #include <cutils/log.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <hardware/led_hal.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <utils/Log.h>
    
    static int fd;
    /** Close this device */
    static int led_close(struct hw_device_t* device)
    {
            close(fd);
            return 0;
    }
    
    static int led_open(struct led_device_t* dev)
    {
            fd = open("/dev/led", O_RDWR);
            ALOGI("led_open : %d", fd);
            if (fd >= 0)
                    return 0;
            else
                    return -1;
    }
    
    static int led_ctrl(struct led_device_t* dev, int which, int status)
    {
            if(fd < 0) {
                fd = open("/dev/led", O_RDWR);
            }
            int ret = ioctl(fd, status, which);
            ALOGI("led_ctrl : %d, %d, %d, %d", which, status, ret, fd);
            return ret;
    }
    
    static struct led_device_t led_dev = {
            .common = {
                    .tag   = HARDWARE_DEVICE_TAG,
                    .close = led_close,
            },
            .led_open  = led_open,
            .led_ctrl  = led_ctrl,
    };
    
    static int led_device_open(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device)
    {
            *device = &led_dev;
            return 0;
    }
    
    static struct hw_module_methods_t led_module_methods = {
        .open = led_device_open,
    };
    
    struct hw_module_t HAL_MODULE_INFO_SYM = {
            .tag = HARDWARE_MODULE_TAG,
        .id = LED_HARDWARE_MODULE_ID,//JNI会通过这个id获取到hal生成的库  
        .methods = &led_module_methods,
    };
    

    (2) 添加led_hal.h:hardware/libhardware/include/hardware/led_hal.h;led_hal.h代码如下:

    #ifndef ANDROID_LED_INTERFACE_H
    #define ANDROID_LED_INTERFACE_H
    #include <stdint.h>
    #include <sys/cdefs.h>
    #include <sys/types.h>
    #include <hardware/hardware.h>
    
    #define LED_HARDWARE_MODULE_ID "led"
    
    __BEGIN_DECLS
    struct led_device_t {
        struct hw_device_t common;
    
            int (*led_open)(struct led_device_t* dev);
            int (*led_ctrl)(struct led_device_t* dev,int which, int status);
    };
    
    __END_DECLS
    
    #endif  // ANDROID_LED_INTERFACE_H

    3. JNI层:

    (1) 创建文件:frameworks/base/services/core/jni/com_android_server_LedService.cpp,代码如下:

    ​
    #define LOG_TAG "LedService"
    
    #include "jni.h"
    #include "JNIHelp.h"
    #include "android_runtime/AndroidRuntime.h"
    #include <utils/misc.h>
    #include <utils/Log.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <hardware/led_hal.h>
    
    namespace android
    {
    
    static led_device_t* led_device;
    
    jint ledOpen(JNIEnv *env, jobject cls)
    {
            jint err;
        hw_module_t* module;
            hw_device_t* device;
            ALOGI("native ledOpen ...");
    
            /* 1. hw_get_module 通过"led"(这是hal的id)找到对应的库.*/
        err = hw_get_module("led", (hw_module_t const**)&module);
        if (err == 0) {
                    /* 2. get device : module->methods->open */
                err = module->methods->open(module, NULL, &device);
                if (err == 0) {
                            /* 3. call led_open */
                    led_device = (led_device_t *)device;
                            return led_device->led_open(led_device);
                } else {
                    return -1;
            }
        }
        return -1;
    }
    
    void ledClose(JNIEnv *env, jobject cls)
    {
            //ALOGI("native ledClose ...");
            //close(fd);
    }
    
    jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status)
    {
            ALOGI("native ledCtrl %d, %d", which, status);
            return led_device->led_ctrl(led_device, which, status);
    }
    //注册本地方法。
    static const JNINativeMethod methods[] = {
            {"native_ledOpen", "()I", (void *)ledOpen},
            {"native_ledClose", "()V", (void *)ledClose},
            {"native_ledCtrl", "(II)I", (void *)ledCtrl},
    };
    int register_android_server_LedService(JNIEnv *env)
    {//本地方法对应的java类LedService
        return jniRegisterNativeMethods(env, "com/android/server/LedService",
                methods, NELEM(methods));
    }
    }
    
    ​

    (2) 修改frameworks/base/services/core/jni/onload.cpp,修改如下:

    
    +int register_android_server_LedService(JNIEnv* env);
     int register_android_server_connectivity_Vpn(JNIEnv* env);
    @@ -74,6 +75,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
         register_android_server_VibratorService(env);
    +    register_android_server_LedService(env);
    
    ​

    (3) 修改:frameworks/base/services/core/jni/Android.mk;添加如下:

         $(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \
    +    $(LOCAL_REL_DIR)/com_android_server_LedService.cpp \

    至此,c/c++代码已经修改完成了。下面进入java程序的修改。

    4. framework层:

    (1) 增加文件:frameworks/base/core/java/android/os/ILedService.aidl。代码如下:

    package android.os;
    
    /** {@hide} */
    interface ILedService
    {
            int ledCtrl(int which, int status);
    }

    (2) 创建文件: frameworks/base/services/core/java/com/android/server/LedService.java。代码如下:

    package com.android.server;
    import android.os.ILedService;
    
    public class LedService extends ILedService.Stub {
        private static final String TAG = "LedService";
    
            /* call native c function to access hardware */
            public int ledCtrl(int which, int status) throws android.os.RemoteException
            {
                    return native_ledCtrl(which, status);
            }
            public LedService() {
                    native_ledOpen();
            }
    
            public static native int native_ledOpen();
            public static native void native_ledClose();
            public static native int native_ledCtrl(int which, int status);
    }

    LedService.java通过JNI,调用本地函数,

    (3) 修改:frameworks/base/Android.mk:

            core/java/android/os/IVibratorService.aidl \
    +       core/java/android/os/ILedService.aidl \
            core/java/android/security/IKeystoreService.aidl \

    (4) 在文件frameworks/base/services/java/com/android/server/SystemServer.java添加如下内容:

    +          
    +            traceBeginAndSlog("StartLedService");
    +            LedService led = new LedService();
    +            ServiceManager.addService("led", led);
    +            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    +
                 if (!disableConsumerIr) {

    到这里,LedService服务就已经注册添加到系统里了。下面是使用服务。

    5. application framework:

    (1)创建文件: frameworks/base/core/java/android/os/SystemLed.java,这个类供app获取,

        通过getSystemService(Context.LED_SERVICE);

    
    package android.os;
    
    import android.content.Context;
    import android.media.AudioAttributes;
    import android.util.Log;
    
    /**
     * Led implementation that controls the main system led.
     *
     * @hide
     */
    public class SystemLed {
        private static final String TAG = "Led";
    
        private final ILedService mService;
        public SystemLed() {
            mService = ILedService.Stub.asInterface(
                    ServiceManager.getService("led"));
        }
    
        public SystemLed(Context context) {
            mService = ILedService.Stub.asInterface(
                    ServiceManager.getService("led"));
        }
    
       public void ledCtrl(int which,int status)
            {
                    try{
                    mService.ledCtrl(which, status);
                    }catch(Exception e){}
            }
    }

     

    (2) 修改文件:frameworks/base/core/java/android/content/Context.java

         public static final String VIBRATOR_SERVICE = "vibrator";
    +    public static final String LED_SERVICE = "led";

    (3) 最后修改文件:frameworks/base/core/java/android/app/SystemServiceRegistry.java

    +import android.os.SystemLed;
     import android.os.UserHandle;
     import android.os.UserManager;
     import android.os.Vibrator;
    @@ -486,6 +487,13 @@ final class SystemServiceRegistry {
                 public Vibrator createService(ContextImpl ctx) {
                     return new SystemVibrator(ctx);
                 }});
    +        registerService(Context.LED_SERVICE, SystemLed.class,
    +                new CachedServiceFetcher<SystemLed>() {
    +            @Override
    +            public SystemLed createService(ContextImpl ctx) {
    +                return new SystemLed(ctx);
    +            }});

    安卓源码的修改已全部完成。

    make update-api  更新api;

    make systemimage -j16  编译system.img 并烧写到开发板。

    6. APP应用:

    由于源码里怎加了很多类,而在安卓sdk中是没有这些类的,解决这个办法就是eclipse或者android studio关联下面这个文件:

    out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar。

    eclipse关联方法:https://blog.csdn.net/mazhaojuan/article/details/21403717

    android studio关联https://www.jetbrains.com/idea/help/configuring-module-dependencies-and-libraries.html

    APP主要代码如下:

     

    ​
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.TextView;
    import android.os.SystemLed;
    import android.os.RemoteException;
    import android.os.ServiceManager;
    
    public class MainActivity extends Activity {
    	
        private SystemLed ledservice = null;
        private static int STATUS = 0,WHICH =1 ;
        private TextView text= null;
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);	
    		text = (TextView) findViewById(R.id.text);
    		text.setText("STATUS:"+STATUS+";WHICH:"+WHICH);
            //通过getSystemService()来获取SystemLed.
    		ledservice = (SystemLed) getSystemService(Context.LED_SERVICE);				
    	}
    	
    	public void add(View view)
    	{
    			ledservice.ledCtrl(++WHICH, ++STATUS);
    			text.setText("STATUS:"+STATUS+";WHICH:"+WHICH);
    	}
    	public void reduce(View view)
    	{
    			ledservice.ledCtrl(--WHICH, --STATUS);
    			text.setText("STATUS:"+STATUS+";WHICH:"+WHICH);
    	}
    
    ​

    7. 效果图:

    (1)APP界面(比较简单,凑合看吧,嘿嘿...):

    (2)内核打印: 命令:cat /dev/kmsg | grep led,点击自增或者自减按钮,会看到输出变化。

    APP代码下载:https://download.csdn.net/download/kai_zone/10575497

    本文涉及的代码:https://download.csdn.net/download/kai_zone/10575551

    容易出现的问题:

    a .设备节点权限问题,没有权限,open设备节点会失败,chmod 777 dev/led给权限,也可以在.rc文件。

    b. classes.jar导包问题,如果app没有你添加的类,肯定是类还没编译到classes.jar文件,重新编译再次导入。

     

     

     

    展开全文
  • 应用程序,操作系统,驱动程序的关系

    千次阅读 多人点赞 2018-07-18 15:39:17
    硬件和软件  计算机资源分为硬件资源和软件资源,硬件资源包括cpu,内存,显卡,网卡,声卡,硬盘等等。... 系统软件就是包各种硬件驱动程序,它们的任务就是用来驱动各种硬件,使硬件完成正常的功能。...

    硬件和软件

          计算机资源分为硬件资源和软件资源,硬件资源包括cpu,内存,显卡,网卡,声卡,硬盘等等。软件资源包括各种程序。每个硬件完成特定的功能,比如显卡完成在显示设备上显示图形,声卡实现声音的处理。再比如,你用qq发送一段文字给一个同学,那么网卡会将信息发送给网络。

    系统软件和应用软件

       系统软件就是包各种硬件驱动程序,它们的任务就是用来驱动各种硬件,使硬件完成正常的功能。比如网卡发送数据,声卡播放声音等。驱动程序提供给应用程序接口,供应用程序调用接口来使用硬件。应用软件接受用户的请求,再通过驱动程序来驱动相关的硬件来实现相关的功能。如下图:

                                                                                      

    没有引入操作系统得问题

           一个计算机上会有很多硬件,所以会有很多的硬件驱动,每个硬件对应的驱动也会不一样,一个应用程序会和很多驱动程序对接,大大加重了应用程序员的编程负担。如下图。

     

                                                             

     

     

                同时,一个系统上面会同时又几个应用程序运行,比如qq和音乐,这两个应用都会使用显示屏来显示,都要使用内存来运行程序,但是硬件资源总是有限的。所以需要使用某种机制来使用和分配资源。设计的时候,这种机制要么放在应用程序中来实现,要么放在驱动程序中来实现。但是无论哪一种,都会增减程序员的负担。

                                                                 

    引入了操作系统之后

            应用程序员只想关心应用程序的开发,而不想花费时间在资源管理和分配上,也不想花时间在区分不同的驱动程序接口上。驱动程序开发人员只想关心开发驱动程序去驱动硬件,不想花费时间在资源管理上。那么久需要引进操作系统了,如下图:

                                                                

    如图可以看到,操作系统的作用是管理各类资源(软件和硬件),并将硬件驱动程序的接口抽象,形成一套简单一直的接口给上层的应用程序应用。因此,应用程序只需要知道这套操作系统提供的编程接口(API)就行了。前面提到系统软件就是各种驱动程序。而我们这里认为系统软件是操作系统。实际上,驱动程序是嵌入到操作系统里面去的,所以操作系统是包括驱动程序的。这就大大加大了驱动程序开发人员的开发难度,因为他们不仅需要熟悉手头硬件的工作原理,更重要的是他们要确保他们写的驱动能够嵌入到操作系统里面去。就这要求他们必须熟悉操作系统提供的用来嵌入驱动程序的接口。

    展开全文
  • Linux系统的硬件驱动程序编写原理

    千次阅读 2009-12-28 18:09:00
    Linux系统的硬件驱动程序编写原理http://www.yesky.com/161/1874161.shtml本文详细地介绍如何Linux系统的硬件驱动程序的编写原理,指出哪些内核例程将会被调用、如何初始化驱动程序及如何分配内存等等。大家一定对...
  • 开发Android硬件驱动程序

    千次阅读 2014-06-07 19:21:08
    一、 1、实现内核驱动程序模块  驱动程序freg的目录结构如下:  ~/android-2.3_r1/kernel/goldfish  ----drivers  ----freg  ----freg.h  ----freg.c
  • 默认情况下,操作系统会自动为大多数硬件安装驱动,但对于主板、显卡等设备,最好为其安装厂商提供的... 下面ghost系统之家小编以安装主板驱动程序为例,介绍电脑硬件驱动程序的安装方法。 步骤1:将主板的驱动...
  • 硬件平台:TI AM335X Starter ... 这次写《Android 从硬件到应用》是想尝试从底层的最简单的GPIO硬件驱动开始,一步一步的向上走,经过硬件抽象层HAL、JNI方法等,最终编写出APP,达到硬件调用的目的,期间会增加一些
  • 开发DSP硬件驱动程序的一种方法

    千次阅读 2011-06-07 21:08:00
    开发DSP硬件驱动程序的一种方法 张 行,雷 勇 (四川大学电气信息学院 四川 成都610065) l 引 言 传统的DSP程序开发包含两方面程序:即配置、控制、中断等管理DSP片内外设、接口的硬件相关程序和基于应用的算法程序...
  • 3.4 关于硬件驱动程序

    2009-12-18 11:14:00
    3.4 关于硬件驱动程序对于早期的Linux而言,寻找特定的硬件驱动程序往往是安装配置中最花费时间的一步。系统管理员甚至不得不自己编写。现在Linux已经得到了绝大部分主流硬件厂商的支持。在Linux安装完成后,往往...
  •  而DOS下的驱动程序安装很不方便,一般需要在config.sys 文件中加上"DEVICE=驱动程序"命令来安装相应的驱动程序,甚至还需要手工跳线,这都要求用户有一定的软硬件基础。而随着Windows操作系统与即插即用(PNP)...
  • 在 Android 从硬件到应用:一步一步向上爬 1 -- 从零编写底层硬件驱动程序  中已经有了编写硬件驱动到linux内核里的步骤,下面就要接着这个工程去看看怎么在硬件抽象层增加硬件模块和我们的内核驱动
  • APP应用程序->应用框架层->... 硬件驱动程序 一、硬件驱动层 进入kernel/drivers文件夹中,创建一文件夹,放入驱动程序。包括头文件,C文件,Makefile,Kconfig。同时对drivers下的Ma...
  • 各位大侠我有一个技术问题想请教,现在有若个B/S应用系统,需要在页面加载的时候,调用PC机端本地一个特定硬件设备的驱动,除了封装OCX控件之外还有什么其他解决方案?还望各位大侠给予指点!
  • 跪求 QT 驱动连接实例,例如用QT写的窗口软件点击某一按钮可以启动摄像头!新手一枚,跪求大神围观!
  • 驱动程序的安装顺序也是一件很重要的事情,它不仅跟系统的正常稳定运行有很大的关系,而且还会对系统的性能有巨大影响。——在平常的使用中因为驱动程序的安装顺序不同,从而造成系统程序不稳定,经常出现错误现象...
  • 一个嵌入式硬件驱动模块通常应包括如下函数:(1)中断服务程序 ISR(2)硬件初始化 A.修改寄存器,设置硬件参数(如 UART 应设置其波特率,AD/DA 设备应设置其采样速率等); B.将中断服务程序入口地址写入中断向...
  • 问题描述:我用USB-CAN转换器连接到电脑时,开始会弹出找到新硬件,需要安装硬件驱动的对话框。开始并没找到驱动,所以点了几个“下一步”就完事了。后面下载到驱动后需要再之前的那个弹出对话框中按提示步骤安装时...
  • 可执行程序来访问硬件驱动程序。 在前一篇文章http://www.linuxidc.com/Linux/2011-07/38977中,我们介绍了如何在Ubuntu 上为Android 系统编写Linux 内核驱动程序。在这个名为hello的Linux 内核驱动程序中,...
  • debian 安装时硬件驱动缺失怎么办?

    千次阅读 2017-04-09 17:39:36
    搜索到自己需要的驱动包,然后下载到U盘根目录下,插入安装系统的电脑上,一般就会自动识别并驱动。 实例:安装时debian8.7时,无线网卡驱动无法正常 提示:iwlwifi-3945-2.ucode 缺失操作步骤 > 登陆...
  • 一些硬件厂商(比如条码枪)有使用java编写驱动程序吗?如果没有,java如何调用它们?
  • 获取电脑硬件对应的驱动程序信息

    千次阅读 2017-06-22 16:18:53
    刚换了工作,入职时候大佬让我研究下 驱动人生/驱动精灵 判断驱动是否正常是怎么做到的 一开始是一脸懵逼的,完全不知道要如何下手,不过应该是获取设备管理器里硬件属性,然后进行判断吧,我就跟据我的猜测进行研究...
  • 在ThinkPad W500 A98上升级Windows 7以及安装硬件驱动和相关程序备份数据先备份数据,由于原来的Windows XP已经不能正常启动,因此就使用光驱启动Windows XP PE,在Windows XP PE下查看需要备份的数据。我平时比较...
  • android层次结构和硬件驱动理解

    千次阅读 2012-03-16 21:05:53
    刚才一口气看完,老罗的csdn博客:“Android硬件抽象层(HAL)概要介绍和学习计划”,感觉对层次结构、驱动过程有了一个理解。并将理解画了张图。 自己刚入门,肯定有很多理解不对的地方,希望大家一起学习,多多...
  • M4000服务器上安装了时统中断卡及设备驱动程序。最近操作系统日志频繁出现警告 信息,意思是时统中断卡出现虚假中断,中断...之前硬件卡和驱动程序运行了一年有余无任何问题。请问出现这样的警告信息是什么原因?谢谢!
  • 升级Linux硬件驱动结构作者:冯立功编译 2005-01-18 10:55:19 来自:开发系统世界 硬件驱动程序是界于硬件和Linux内核之间的软件接口,是一种低级的、专用于某一硬件的软件组件。这种软件组件可以使硬件与更普遍的...
  • Linux设备驱动程序工作原理

    千次阅读 2019-01-08 00:01:17
    Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全... 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件...
  • 计算机相应硬件驱动程序的关系

    千次阅读 2006-12-08 11:16:00
    驱动程序即添加到操作系统中的一小块代码,其中包含有关硬件设备的信息。有了此信息,计算机就可以与设备进行通信。驱动程序硬件厂商根据操作系统编写的 配置文件,可以说没有驱动程序,计算机中的硬件就无法工作...
  • refer to 在Android硬件抽象层增加接口模块访问硬件驱动程序

空空如也

1 2 3 4 5 ... 20
收藏数 370,580
精华内容 148,232
关键字:

硬件驱动