一、手機開機狀態(tài)的驅(qū)動安裝

創(chuàng)新互聯(lián)公司服務(wù)項目包括城區(qū)網(wǎng)站建設(shè)、城區(qū)網(wǎng)站制作、城區(qū)網(wǎng)頁制作以及城區(qū)網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,城區(qū)網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到城區(qū)省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
現(xiàn)在手機處于開機狀態(tài)(打開USB調(diào)試并且授權(quán)電腦進行調(diào)試)連接電腦.
右鍵計算機-屬性-選擇左上角的
設(shè)備管理器
找到
其他設(shè)備
有個帶著黃色感嘆號的Android設(shè)備(如下圖),這就是你的一加手機,win8.1的系統(tǒng)無法自己安裝...
右鍵該設(shè)備
選擇"更新驅(qū)動程序軟件"
選擇"瀏覽計算機以查找驅(qū)動程序軟件"
瀏覽,將其定位在"C:\Program
Files\ONEPLUS\USB
Driver\"目錄,下一步,即可完成第一部分的驅(qū)動.
等待安裝完成后,電腦"設(shè)備管理器"可以看到,出現(xiàn)了"Android
Composite
ADB
interface":
二、Bootloader狀態(tài)的驅(qū)動安裝
手機斷開數(shù)據(jù)線,關(guān)機.
關(guān)機狀態(tài)下,按住"開始鍵+音量上鍵",進入Fastboot.此時重新連接電腦.
在這里,選擇"設(shè)備管理器-查看-顯示隱藏的驅(qū)動".
這個驅(qū)動能自己安裝,等待安裝完成后,電腦"設(shè)備管理器"可以看到,出現(xiàn)了"Android
Bootloader
interface":
三、Recovery狀態(tài)的驅(qū)動安裝
手機斷開數(shù)據(jù)線,按住關(guān)機鍵5S,強制關(guān)機.
關(guān)機狀態(tài)下,按住"開始鍵+音量下鍵",進入Recovery.此時重新連接電腦
在電腦的"設(shè)備管理器-其他設(shè)備"又能找到帶黃色嘆號的設(shè)備,右鍵它,選擇"更新驅(qū)動程序軟件"
這次需要選擇"從計算機的設(shè)備驅(qū)動程序列表中選取"(也就是下面那個選項)
到了下面的界面,選擇Android
Phone(電腦上有兩個,一個不能用,所以不行的話是另外一個)
這下看到了
Oneplus,點擊選擇,然后下一步,完成安裝.
需要啟動Android驅(qū)動模塊Makefile編寫。
PCI是一種外設(shè)總線規(guī)范。我們先來看一下什么是總線:總線是一種傳輸信號的路徑或信道。典型情況是,總線是連接于一個或多個導體的電氣連線,總線上連接的所有設(shè)備可在同一時間收到所有的傳輸內(nèi)容。總線由電氣接口和編程接口組成。本文討論Linux 下的設(shè)備驅(qū)動,所以,重點關(guān)注編程接口。
CI是Peripheral Component Interconnect(外圍設(shè)備互聯(lián))的簡稱,是普遍使用在桌面及更大型的計算機上的外設(shè)總線。PCI架構(gòu)被設(shè)計為ISA標準的替代品,他有三個主要目標:獲得在計算機和外設(shè)之間傳輸數(shù)據(jù)時更好的性能;盡可能的平臺無關(guān);簡化往系統(tǒng)中添加和刪除外設(shè)的工作。
上一篇文章,在解析初始化GraphicBuffer中,遇到一個ion驅(qū)動,對圖元進行管理。首先看看ion是怎么使用的:
我們按照這個流程分析ion的源碼。
如果對ion使用感興趣,可以去這篇文章下面看
本文基于Android的Linux內(nèi)核版本3.1.8
遇到什么問題歡迎來本文討論
什么是ion?如果是音視頻,Camera的工程師會對這個驅(qū)動比較熟悉。最早的GPU和其他驅(qū)動協(xié)作申請一塊內(nèi)存進行繪制是使用比較粗暴的共享內(nèi)存。在Android系統(tǒng)中使用的是匿名內(nèi)存。最早由三星實現(xiàn)了一個Display和Camera共享內(nèi)存的問題,曾經(jīng)在Linux社區(qū)掀起過一段時間。之后各路大牛不斷的改進之下,就成為了dma_buf驅(qū)動。并在 Linux-3.3 主線版本合入主線。現(xiàn)在已經(jīng)廣泛的運用到各大多媒體開發(fā)中。
首先介紹dma_buf的2個角色,importer和exporter。importer是dma_buf驅(qū)動中的圖元消費者,exporter是dma_buf驅(qū)動中的圖元生產(chǎn)者。
這里借用大佬的圖片:
ion是基于dma_buf設(shè)計完成的。經(jīng)過閱讀源碼,其實不少思路和Android的匿名內(nèi)存有點相似。閱讀本文之前就算不知道dma_buf的設(shè)計思想也沒關(guān)系,我不會仔細到每一行,我會注重其在gralloc服務(wù)中的申請流程,看看ion是如何管理共享內(nèi)存,為什么要拋棄ashmem。
我們先來看看ion的file_operation:
只有一個open和ioctl函數(shù)。但是沒有mmap映射。因此mmap映射的時候一定其他對象在工作。
我們關(guān)注顯卡英偉達的初始化模塊。
文件:/ drivers / staging / android / ion / tegra / tegra_ion.c
module_platform_driver實際上就是我之前經(jīng)常提到過的module_init的一個宏,多了一個register注冊到對應(yīng)名字的平臺中的步驟。在這里面注冊了一個probe方法指針,probe指向的tegra_ion_probe是加載內(nèi)核模塊注冊的時候調(diào)用。
先來看看對應(yīng)的結(jié)構(gòu)體:
再來看看對應(yīng)ion內(nèi)的堆結(jié)構(gòu)體:
完成的事情如下幾個步驟:
我們不關(guān)注debug模式。其實整個就是我們分析了很多次的方法。把這個對象注冊miscdevice中。等到insmod就會把整個整個內(nèi)核模塊從dev_t的map中關(guān)聯(lián)出來。
我們來看看這個驅(qū)動結(jié)構(gòu)體:
文件:/ drivers / staging / android / ion / ion_heap.c
這里有四個不同堆會申請出來,我們主要來看看默認的ION_HEAP_TYPE_SYSTEM對應(yīng)的heap流程。
其實真正象征ion的內(nèi)存堆是下面這個結(jié)構(gòu)體
不管原來的那個heap,會新建3個ion_system_heap,分別order為8,4,0,大于4為大內(nèi)存。意思就是這個heap中持有一個ion_page_pool 頁資源池子,里面只有對應(yīng)order的2的次冪,內(nèi)存塊。其實就和伙伴系統(tǒng)有點相似。
還會設(shè)置flag為ION_HEAP_FLAG_DEFER_FREE,這個標志位后面會用到。
文件:/ drivers / staging / android / ion / ion_page_pool.c
在pool中分為2個鏈表一個是high_items,另一個是low_items。他們之間的區(qū)分在此時就是以2為底4的次冪為分界線。
文件:/ drivers / staging / android / ion / ion.c
因為打開了標志位ION_HEAP_FLAG_DEFER_FREE和heap存在shrink方法。因此會初始化兩個回收函數(shù)。
文件:/ drivers / staging / android / ion / ion_heap.c
此時會創(chuàng)建一個內(nèi)核線程,調(diào)用ion_heap_deferred_free內(nèi)核不斷的循環(huán)處理。不過由于這個線程設(shè)置的是SCHED_IDLE,這是最低等級的時間片輪轉(zhuǎn)搶占。和Handler那個adle一樣的處理規(guī)則,就是閑時處理。
在這個循環(huán)中,不斷的循環(huán)銷毀處理heap的free_list里面已經(jīng)沒有用的ion_buffer緩沖對象。
文件:/ drivers / staging / android / ion / ion_system_heap.c
注冊了heap的銷毀內(nèi)存的方法。當系統(tǒng)需要銷毀頁的時候,就會調(diào)用通過register_shrinker注冊進來的函數(shù)。
文件:/ drivers / staging / android / ion / ion_page_pool.c
整個流程很簡單,其實就是遍歷循環(huán)需要銷毀的頁面數(shù)量,接著如果是8的次冪就是移除high_items中的page緩存。4和0則銷毀low_items中的page緩存。至于為什么是2的次冪其實很簡單,為了銷毀和申請簡單。__free_pages能夠整頁的銷毀。
文件:/ drivers / staging / android / ion / ion.c
主要就是初始化ion_client各個參數(shù),最后把ion_client插入到ion_device的clients。來看看ion_client結(jié)構(gòu)體:
核心還是調(diào)用ion_alloc申請一個ion緩沖區(qū)的句柄。最后把數(shù)據(jù)拷貝會用戶空間。
這個實際上就是找到最小能承載的大小,去申請內(nèi)存。如果8kb申請內(nèi)存,就會拆分積分在0-4kb,4kb-16kb,16kb-128kb區(qū)間找。剛好dma也是在128kb之內(nèi)才能申請。超過這個數(shù)字就禁止申請。8kb就會拆成2個4kb保存在第一個pool中。
最后所有的申請的page都添加到pages集合中。
文件:/ drivers / staging / android / ion / ion_page_pool.c
能看到此時會從 ion_page_pool沖取出對應(yīng)大小區(qū)域的空閑頁返回上層,如果最早的時候沒有則會調(diào)用ion_page_pool_alloc_pages申請一個新的page。由于引用最終來自ion_page_pool中,因此之后申請之后還是在ion_page_pool中。
這里的處理就是為了避免DMA直接內(nèi)存造成的緩存差異(一般的申請,默認會帶一個DMA標志位)。換句話說,是否打開cache其實就是,關(guān)閉了則使用pool的cache,打開了則不使用pool緩存,只依賴DMA的緩存。
我們可以看另一個dma的heap,它是怎么做到dma內(nèi)存的一致性.
文件: drivers / staging / android / ion / ion_cma_heap.c
能看到它為了能辦到dma緩存的一致性,使用了dma_alloc_coherent創(chuàng)建了一個所有強制同步的地址,也就是沒有DMA緩存的地址。
這里出現(xiàn)了幾個新的結(jié)構(gòu)體,sg_table和scatterlist
文件:/ lib / scatterlist.c
這里面實際上做的事情就是一件:初始化sg_table.
sg_table中有一個核心的對象scatterlist鏈表。如果pages申請的對象數(shù)量PAGE_SIZE/sizeof(scatterlist),每一項sg_table只有一個scatterlist。但是超出這個數(shù)字就會增加一個scatterlist。
用公式來說:
換句話說,每一次生成scatterlist的鏈表就會直接盡可能占滿一頁,讓內(nèi)存更好管理。
返回了sg_table。
初始化ion_handle,并且記錄對應(yīng)的ion_client是當前打開文件的進程,并且設(shè)置ion_buffer到handle中。使得句柄能夠和buffer關(guān)聯(lián)起來。
每當ion_buffer需要銷毀,
一.認識android的架構(gòu)
Android其本質(zhì)就是在標準的Linux系統(tǒng)上增加了Java虛擬機Dalvik,并在Dalvik虛擬機上搭建了一個JAVA的application framework,所有的應(yīng)用程序都是基于JAVA的application framework之上。
android分為四個層,從高層到低層分別是應(yīng)用程序?qū)印?yīng)用程序框架層、系統(tǒng)運行庫層和linux核心層。
二.搭建環(huán)境
搭建開發(fā)環(huán)境
對國內(nèi)的開發(fā)者來說最痛苦的是無法去訪問android開發(fā)網(wǎng)站。為了更好的認識世界,對程序員來說,會翻墻也是的一門技術(shù),帶你去領(lǐng)略墻外的世界,好了,不廢話了, 國內(nèi)開發(fā)者訪問(androiddevtools) 上面已經(jīng)有了所有你要的資源,同時可以下載到我們的主角framework
但是這樣的搭建只能去閱讀源代碼,我們無法去更進一步去實現(xiàn)自己的rom,我們看到錘子的系統(tǒng)在早期的開放rom是自己從新實現(xiàn)了framework的代碼,現(xiàn)在看起來他成功了,所以我們還要去搭建android系統(tǒng)的源碼編譯環(huán)境。
搭建源碼編譯環(huán)境
三.開始主題
在一開始寫c程序的時候都有一個運行的入口,比如
#include iostream
#include cmath
#include algorithm
using namespace std;
//這里的main就是應(yīng)用的入口
int main(int argc, const char * argv[]){
return 0;
}
在計算機網(wǎng)絡(luò)原理中我們用socket實現(xiàn)一個服務(wù)器端,不斷的接聽客戶端的訪問,而且他的代碼是這樣實現(xiàn)的:
#include winsock2.h
#pragma comment(lib, "WS2_32.lib")
#include stdio.h
void main()
{
WORD wVersionRequested;//版本號
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);//2.2版本的套接字
//加載套接字庫,如果失敗返回
err = WSAStartup(wVersionRequested, wsaData);
if (err != 0)
{
return;
}
//判斷高低字節(jié)是不是2,如果不是2.2的版本則退出
if (LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2)
{
return;
}
//創(chuàng)建流式套接字,基于TCP(SOCK_STREAM)
SOCKET socSrv = socket(AF_INET, SOCK_STREAM, 0);
//Socket地址結(jié)構(gòu)體的創(chuàng)建
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//轉(zhuǎn)換Unsigned long型為網(wǎng)絡(luò)字節(jié)序格
addrSrv.sin_family = AF_INET;//指定地址簇
addrSrv.sin_port = htons(6000);
//指定端口號,除sin_family參數(shù)外,其它參數(shù)都是網(wǎng)絡(luò)字節(jié)序,因此需要轉(zhuǎn)換
//將套接字綁定到一個端口號和本地地址上
bind(socSrv, (SOCKADDR*)addrSrv, sizeof(SOCKADDR));//必須用sizeof,strlen不行
listen(socSrv, 5);
SOCKADDR_IN addrClient;//字義用來接收客戶端Socket的結(jié)構(gòu)體
int len = sizeof(SOCKADDR);//初始化參數(shù),這個參數(shù)必須進行初始化,sizeof
//循環(huán)等待接受客戶端發(fā)送請求
while (1)
{
//等待客戶請求到來;當請求到來后,接受連接請求,
//返回一個新的對應(yīng)于此次連接的套接字(accept)。
//此時程序在此發(fā)生阻塞
SOCKET sockConn = accept(socSrv, (SOCKADDR*)addrClient, len);
char sendBuf[100];
sprintf(sendBuf, "Welcome %s to JoyChou",
inet_ntoa(addrClient.sin_addr));//格式化輸出
//用返回的套接字和客戶端進行通信
send(sockConn, sendBuf, strlen(sendBuf)+1, 0);//多發(fā)送一個字節(jié)
//接收數(shù)據(jù)
char recvBuf[100];
recv(sockConn, recvBuf, 100, 0);
printf("%s\\n", recvBuf);
closesocket(sockConn);
}
}
他采用了一個while死循環(huán)去監(jiān)聽客戶端的請求。
先上源代碼
public final class ActivityThread {
public static void main(String[] args) {
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("pre-initialized");
Looper.prepareMainLooper();
//從中可以看到為app開辟了一個線程進入了looper之中
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
看到源碼失望了,沒有一個while循環(huán)啊,其實用了他方法實現(xiàn)
//用一個looper的機制循環(huán)監(jiān)聽響應(yīng)
Looper.prepareMainLooper();
Looper.loop();
進一步深入代碼
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// 在這里看到了一個循環(huán)監(jiān)聽消息
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
Printer logging = me.mLogging;
if (logging != null) {
logging.println(" Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println(" Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
說到 android 驅(qū)動是離不開 Linux 驅(qū)動的。Android 內(nèi)核采用的是 Linux2.6 內(nèi)核 (最近Linux 3.3 已經(jīng)包含了一些 Android 代碼)。但 Android 并沒有完全照搬 Linux 系統(tǒng)內(nèi)核,除了對Linux 進行部分修正,還增加了不少內(nèi)容。android 驅(qū)動 主要分兩種類型:Android 專用驅(qū)動 和 Android 使用的設(shè)備驅(qū)動(linux)。
Android 專有驅(qū)動程序:
1)Android Ashmem 匿名共享內(nèi)存; 為用戶空間程序提供分配內(nèi)存的機制,為進程間提供大塊共享內(nèi)存,同時為內(nèi)核提供回收和管理這個內(nèi)存。
2)Android Logger 輕量級的LOG(日志) 驅(qū)動;
3)Android Binder 基于 OpenBinder 框架的一個驅(qū)動;
4)Android Power Management 電源管理模塊;
5)Low Memory Killer 低內(nèi)存管理器;
6)Android PMEM 物理內(nèi)存驅(qū)動;
7)USB Gadget USB 驅(qū)動(基于 gaeget 框架);
8)Ram Console 用于調(diào)試寫入日志信息的設(shè)備;
9)Time Device 定時控制設(shè)備;
10)Android Alarm 硬件時鐘;
Android 上的設(shè)備驅(qū)動:
1)Framebuff 顯示驅(qū)動;
2)Event 輸入設(shè)備驅(qū)動;
3)ALSA 音頻驅(qū)動;
4)OSS 音頻驅(qū)動;
5)v412攝像頭:視頻驅(qū)動;
6)MTD 驅(qū)動;
7)藍牙驅(qū)動;
8)WLAN 設(shè)備驅(qū)動;
Android 專有驅(qū)動程序
1.Android Ashmem
為用戶空間程序提供分配內(nèi)存的機制,為進程間提供大塊共享內(nèi)存,同時為內(nèi)核提供回收和管理這個內(nèi)存。
設(shè)備節(jié)點:/dev/ashmen .主設(shè)備號 10.
源碼位置: include/linux/ashmen.h Kernel /mm/ashmen.c
相比于 malloc 和 anonymous/named mmap 等傳統(tǒng)的內(nèi)存分配機制,其優(yōu)勢是通過內(nèi)核驅(qū)動提供了輔助內(nèi)核的內(nèi)存回收算法機制(pin/unoin)
2.Android Logger
無論是底層的源代碼還上層的應(yīng)用,我們都可以使用 logger 這個日志設(shè)備看、來進行調(diào)試。
設(shè)備節(jié)點: /dev/log/main /dev/log/event /dev/log/radio
源碼位置:include/linux/logger.h include/linux/logger.c
3.Android Binder
IPC Binder 一種進程間通信機制。他的進程能夠為其它進程提供服務(wù) ----- 通過標準的 Linux 系統(tǒng)調(diào)用 API。
設(shè)備節(jié)點 :/dev/binder
源碼位置:Kernel/include/linux/binder.h Kernel/drivers/misc/binder.c
4.Android Power Management
一個基于標準 linux 電源管理的輕量級 Android 電源管理系統(tǒng),在 drivers/android/power.c kernel/power/
5.Low Memory Killer
它在用戶空間中指定了一組內(nèi)存臨界值,當其中某個值與進程描述中的 oom_adj 值在同一范圍時,該進程將被Kill掉(在parameters/adj中指定oome_adj 的最小值)。它與標準的Linux OOM機制類似,只是實現(xiàn)方法不同
源碼位置:drivers/misc/lowmemorykiller.c
6.Android PMEM
PMEM 主要作用就是向用戶空間提供連續(xù)的物理內(nèi)存區(qū)域。
1.讓 GPU 或 VPU 緩沖區(qū)共享 CPU 核心。
2.用于 Android service 堆。
源碼位置:include/linux/android_pmem.h drivers/android/pmem.c
7.USB Gadget
基于標準 Linux USB gaeget 驅(qū)動框架的設(shè)備驅(qū)動。
源碼位置:drivers/usb/gadet/
8.Ram Console
為了提供調(diào)試功能,android 允許將調(diào)試日志信息寫入這個設(shè)備,它是基于 RAM 的 buffer.
源碼位置: drivers/staging/android/ram_console.c
9.Time Device
定時控制,提供了對設(shè)備進行定時控制的功能。
源碼位置:drivers/staging/android/timed_output.c(timed_gpio.c)
10.Android Alarm
提供一個定時器,用于把設(shè)備從睡眠狀態(tài)喚醒,同時它還提供了一個即使在設(shè)備睡眠時也會運行的時鐘基準。
設(shè)備節(jié)點:/dev/alarm
源碼位置:drivers/trc/alarm.c
Android 設(shè)備驅(qū)動
1. Framebuffer 幀緩存設(shè)備
Framebuffer 驅(qū)動在 Linux 中是標準的顯示設(shè)備的驅(qū)動。對于 PC 系統(tǒng),它是顯卡的驅(qū)動 ; 對于嵌入式 SOC 處理器系統(tǒng),它是 LCD 控制器或者其他顯示控制器的驅(qū)動。它是一個字符設(shè)備,在文件系統(tǒng)中設(shè)備節(jié)點通常是 /dev/fbx 。 每個系統(tǒng)可以有多個顯示設(shè)備 , 依次用 /dev/fbO 、 /dev/fb l
等來表示。在 Android 系統(tǒng)中主設(shè)備號為 29 ,次設(shè)備號遞增生成。
Android 對 Framebuffer 驅(qū)動的使用方式是標準的 , 在 / dev / graphie / 中的 Framebuffer 設(shè)備節(jié)點由 init 進程自動創(chuàng)建 , 被 libui 庫調(diào)用 。 Android 的 GUI 系統(tǒng)中 , 通過調(diào)用 Framebuffer 驅(qū)動的標準接口,實現(xiàn)顯示設(shè)備的抽象。
Framebuff的結(jié)構(gòu)框架和實現(xiàn) :
linux LCD驅(qū)動(二)--FrameBuffer
Linux LCD驅(qū)動(四)--驅(qū)動的實現(xiàn)
2.Event輸入設(shè)備驅(qū)動
Input 驅(qū)動程序是 Linux 輸入設(shè)備的驅(qū)動程序 , 分為游戲桿 (joystick) 、 鼠標 (mouse 和 mice)和事件設(shè)備 (Event queue)3 種驅(qū)動程序。其中事件驅(qū)動程序是目前通用的程序,可支持鍵盤 、 鼠標、觸摸屏等多種輸入設(shè)備。 Input 驅(qū)動程序的主設(shè)備號是 l3 ,每一種 Input 設(shè)備從設(shè)備號占 用5 位 , 3 種從設(shè)備號分配是 : 游戲桿 0 ~ 61 ; Mouse 鼠標 33 ~ 62 ; Mice 鼠標 63 ; 事件設(shè)備 64 ~ 95 ,各個具體的設(shè)備在 misc 、 touchscreen 、 keyboard 等目錄中。
Event 設(shè)備在用戶空問使用 read 、 ioctl 、 poll 等文件系統(tǒng)的接口操作, read 用于讀取輸入信息, ioctl 用于獲取和設(shè)置信息, poll 用于用戶空間的阻塞,當內(nèi)核有按鍵等中斷時,通過在中斷中喚醒內(nèi)核的 poll 實現(xiàn)。
Event 輸入驅(qū)動的架構(gòu)和實現(xiàn):
Linux設(shè)備驅(qū)動之——input子系統(tǒng)
3.ALSA音頻驅(qū)動
高級 Linux 聲音體系 ALSA(Advanced Linux Sound Architecture ) 是為音頻系統(tǒng)提供驅(qū)動 的Linux 內(nèi)核組件,以替代原先的開發(fā)聲音系統(tǒng) OSS 。它是一個完全開放源代碼的音頻驅(qū)動程序集 ,除了像 OSS 那樣提供一組內(nèi)核驅(qū)動程序模塊之外 , ALSA 還專門為簡化應(yīng)用程序的編寫提供相應(yīng)的函數(shù)庫,與 OSS 提供的基于 ioctl 等原始編程接口相比, ALSA 函數(shù)庫使用起來要更加方便一些
利用該函數(shù)庫,開發(fā)人員可以方便、快捷地開發(fā)出自己的應(yīng)用程序,細節(jié)則留給函數(shù)庫進行內(nèi)部處理 。 所以雖然 ALSA 也提供了類似于 OSS 的系統(tǒng)接口 , 但建議應(yīng)用程序開發(fā)者使用音頻函數(shù)庫,而不是直接調(diào)用驅(qū)動函數(shù)。
ALSA 驅(qū)動的主設(shè)備號為 116 ,次設(shè)備號由各個設(shè)備單獨定義,主要的設(shè)備節(jié)點如下:
/ dev / snd / contmlCX —— 主控制 ;
/ dev / snd / pcmXXXc —— PCM 數(shù)據(jù)通道 ;
/ dev / snd / seq —— 順序器;
/ dev / snd / timer —— 定義器。
在用戶空問中 , ALSA 驅(qū)動通常配合 ALsA 庫使用 , 庫通過 ioctl 等接口調(diào)用 ALSA 驅(qū)動程序的設(shè)備節(jié)點。對于 AIJSA 驅(qū)動的調(diào)用,調(diào)用的是用戶空間的 ALsA 庫的接口,而不是直接調(diào)用 ALSA 驅(qū)動程序。
ALSA 驅(qū)動程序的主要頭文件是 include / sound ./ sound . h ,驅(qū)動核心數(shù)據(jù)結(jié)構(gòu)和具體驅(qū)動的注冊函數(shù)是 include / sound / core . h ,驅(qū)動程序 的核心實現(xiàn)是 Sound / core / sound . c 文件。
ALSA 驅(qū)動程序使用下面的函數(shù)注冊控制和設(shè)備:
int snd _ pcm _ new (struct snd _ card * card , char * id , int device , int playback _ count , int capture _ count , struct snd _ pcm ** rpcm) ;
int snd ctl _ add(struct snd _ card * card , struct snd _ kcontrol * kcontro1) ;
ALSA 音頻驅(qū)動在內(nèi)核進行 menuconfig 配置時 , 配置選項為 “ Device Drivers ” “ Sound c ard support ” 一 “ Advanced Linux Sound Architecture ” 。子選項包含了 Generic sound devices( 通用聲音設(shè)備 ) 、 ARM 體系結(jié)構(gòu)支持,以及兼容 OSS 的幾個選項。 ALsA 音頻驅(qū)動配置對應(yīng)的文件是sound / core / Kconfig 。
Android 沒有直接使用 ALSA 驅(qū)動,可以基于 A-LSA 驅(qū)動和 ALSA 庫實現(xiàn) Android Audio 的硬件抽象層; ALSA 庫調(diào)用內(nèi)核的 ALSA 驅(qū)動, Audio 的硬件抽象層調(diào)用 ALSA 庫。
4.OSS音頻驅(qū)動
OSS(Open Sound System開放聲音系統(tǒng))是 linux 上最早出現(xiàn)的聲卡驅(qū)動。OSS 由一套完整的內(nèi)核驅(qū)動程序模塊組成,可以為絕大多數(shù)聲卡提供統(tǒng)一的編程接口。
OSS 是字符設(shè)備,主設(shè)備號14,主要包括下面幾種設(shè)備文件:
1) /dev/sndstat
它是聲卡驅(qū)動程序提供的簡單接口,它通常是一個只讀文件,作用也只限于匯報聲卡的當前狀態(tài)。(用于檢測聲卡)
2)/dev/dsp
用于數(shù)字采樣和數(shù)字錄音的設(shè)備文件。對于音頻編程很重要。實現(xiàn)模擬信號和數(shù)字信號的轉(zhuǎn)換。
3)/dev/audio
類似于/dev/dsp,使用的是 mu-law 編碼方式。
4)/dev/mixer
用于多個信號組合或者疊加在一起,對于不同的聲卡來說,其混音器的作用可能各不相同。
5)/dev/sequencer
這個設(shè)備用來對聲卡內(nèi)建的波表合成器進行操作,或者對 MIDI 總線上的樂器進行控制。
OSS 驅(qū)動所涉及的文件主要包括:
kernel/include/linux/soundcard.h
kernel/include/linux/sound.h 定義 OSS 驅(qū)動的次設(shè)備號和注冊函數(shù)
kernel/sound_core.c OSS核心實現(xiàn)部分
5.V4l2視頻驅(qū)動
V4L2是V4L的升級版本,為linux下視頻設(shè)備程序提供了一套接口規(guī)范。包括一套數(shù)據(jù)結(jié)構(gòu)和底層V4L2驅(qū)動接口。V4L2提供了很多訪問接口,你可以根據(jù)具體需要選擇操作方法。需要注意的是,很少有驅(qū)動完全實現(xiàn)了所有的接口功能。所以在使用時需要參考驅(qū)動源碼,或仔細閱讀驅(qū)動提供者的使用說明。
V4L2的主設(shè)備號是81,次設(shè)備號:0~255,這些次設(shè)備號里也有好幾種設(shè)備(視頻設(shè)備、Radio設(shè)備、Teletext、VBI)。
V4L2的設(shè)備節(jié)點: /dev/videoX, /dev/vbiX and /dev/radioX
Android 設(shè)備驅(qū)動(下)
MTD 驅(qū)動
Flash 驅(qū)動通常使用 MTD (memory technology device ),內(nèi)存技術(shù)設(shè)備。
MTD 的字符設(shè)備:
/dev/mtdX
主設(shè)備號 90.
MTD 的塊設(shè)備:
/dev/block/mtdblockX
主設(shè)備號 13.
MTD 驅(qū)動源碼
drivers/mtd/mtdcore.c:MTD核心,定義MTD原始設(shè)備
drivers/mtd/mtdchar.c:MTD字符設(shè)備
drivers/mtd/mtdblock.c:MTD塊設(shè)備
MTD 驅(qū)動程序是 Linux 下專門為嵌入式環(huán)境開發(fā)的新一類驅(qū)動程序。Linux 下的 MTD 驅(qū)動程序接口被劃分為用戶模塊和硬件模塊:
用戶模塊 提供從用戶空間直接使用的接口:原始字符訪問、原始塊訪問、FTL (Flash Transition Layer)和JFS(Journaled File System)。
硬件模塊 提供內(nèi)存設(shè)備的物理訪問,但不直接使用它們,二十通過上述的用戶模塊來訪問。這些模塊提供了閃存上讀、寫和擦除等操作的實現(xiàn)。
藍牙驅(qū)動
在 Linux 中,藍牙設(shè)備驅(qū)動是網(wǎng)絡(luò)設(shè)備,使用網(wǎng)絡(luò)接口。
Android 的藍牙協(xié)議棧使用BlueZ實現(xiàn)來對GAP, SDP以及RFCOMM等應(yīng)用規(guī)范的支持,并獲得了SIG認證。由于Bluez使用GPL授權(quán), 所以Android 框架通過D-BUS IPC來與bluez的用戶空間代碼交互以避免使用未經(jīng)授權(quán)的代碼。
藍牙協(xié)議部分頭文件:
include/net/bluetooth/hci_core.h
include/net/bluetooth/bluetooth.h
藍牙協(xié)議源代碼文件:
net/bluetooth/*
藍牙驅(qū)動程序部分的文件:
drivers/bluetooth/*
藍牙的驅(qū)動程序一般都通過標準的HCI控制實現(xiàn)。但根據(jù)硬件接口和初始化流程的不同,又存在一些差別。這類初始化動作一般是一些晶振頻率,波特率等基礎(chǔ)設(shè)置。比如CSR的芯片一般通過BCSP協(xié)議完成最初的初始化配置,再激活標準HCI控制流程。對Linux來說,一旦bluez可以使用HCI與芯片建立起通信(一般是hciattach + hciconfig),便可以利用其上的標準協(xié)議(SCO, L2CAP等),與藍牙通信,使其正常工作了。
WLAN 設(shè)備驅(qū)動(Wi-Fi)(比較復雜我面會專門寫個wifi分析)
在linux中,Wlan設(shè)備屬于網(wǎng)絡(luò)設(shè)備,采用網(wǎng)絡(luò)接口。
Wlan在用戶空間采用標準的socket接口進行控制。
WiFi協(xié)議部分頭文件:
include/net/wireless.h
WiFi協(xié)議部分源文件:
net/wireless/*
WiFi驅(qū)動程序部分:
drivers/net/wireless/*
名稱欄目:android驅(qū)動,android驅(qū)動開發(fā)
標題URL:http://chinadenli.net/article42/dsiochc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、云服務(wù)器、關(guān)鍵詞優(yōu)化、小程序開發(fā)、動態(tài)網(wǎng)站、網(wǎng)站設(shè)計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)