菜鳥與月薪10萬大神的差距都在這 : Android、嵌入式Linux開發者必讀 !
文章來源:xgbing (文末有彩蛋)
嵌入式linux和嵌入式android系統有什麼區別和聯絡?
這個問題很多人問,尤其是初入嵌入式的菜鳥。其實大家都認為android是java,已經不是linux,殊不知android就是靠著linux 才發展起來的,現在來說說有啥區別吧。
嵌入式android原始碼架構:uboot+linux kernel+android(包含檔案系統,虛擬機器,UI)
嵌入式linux:這是大部分人認識的linux uboot+linux kernel+檔案系統+QT(UI),
當然兩者的linux 核心因為上層UI的不同會稍有差別,不過還是非常接近的,做過linux的人可以無縫切換到android底層開發,所以大家說的學習android系統,其實最重要的就是學習linux驅動,再加一下android下的專門的HAL,JNI,java等等,不過大公司android相關部分也是專門的人做的了。
甚至連QT都不用了,因為linux很多裝置都是沒有UI的,所以要來幹啥?直接無介面,照樣是嵌入式linux。
現在大家說的什麼嵌入式debian,ubuntu,其實也是站在linux巨人的肩膀上,其實都不算是linux的分支,只算是linux的延伸,小變化而已。看到這裡大家知道嵌入式linux的強大了吧,反正是比wince 強大N倍啊。
O(∩_∩)O~,所以啊,學習嵌入式android,其實底下就是學習uboot,linux核心啊,不會搞這些就像搞應用一樣,所以大家以為android就是java,是非常片面的。
以前老的,說了一下區別,可以參考一下
也為大家推薦了技術教程:
課程名稱 | 課程連結 | 技術分類 |
Linux視訊教程 | https://edu.csdn.net/course/detail/9128?utm_source=blog11xk | 系統/網路/運維 > Linux |
zabbix企業實戰應用 | https://edu.csdn.net/course/detail/9124?utm_source=blog11xk | 系統/網路/運維 > Linux |
Linux 實用講解+實操+面試題 | https://edu.csdn.net/course/detail/9116?utm_source=blog11xk | 系統/網路/運維 > Linux |
ARCH -- 這是Android修改了arch/arm下面的一些檔案:
arch/arm:
Chg: arch/arm/kernel/entry-armv.S
Chg: arch/arm/kernel/module.c
Chg: arch/arm/kernel/process.c
Chg: arch/arm/kernel/ptrace.c
Chg: arch/arm/kernel/setup.c
Chg: arch/arm/kernel/signal.c
Chg: arch/arm/kernel/traps.c
Chg: arch/arm/mm/cache-v6.S
Chg: arch/arm/vfp/entry.S
Chg: arch/arm/vfp/vfp.h
Chg: arch/arm/vfp/vfphw.S
Chg: arch/arm/vfp/vfpmodule.c
Goldfish -- 這是Android為了模擬器所開發的一個虛擬硬體平臺。Goldfish執行arm926T指令(在2.6.29中,goldfish也支援ATMv7指令),但是在實際的裝置中,該虛擬平臺的檔案不會被編譯。
arch/arm/mach-goldfish:
New: arch/arm/mach-goldfish/audio.c
New: arch/arm/mach-goldfish/board-goldfish.c
New: arch/arm/mach-goldfish/pdev_bus.c
New: arch/arm/mach-goldfish/pm.c
New: arch/arm/mach-goldfish/switch.c
New: arch/arm/mach-goldfish/timer.c
YAFFS2 -- 和PC把檔案儲存在硬碟上不一樣, 移動裝置一般把Flash作為儲存裝置。尤其是NAND flash應用非常廣泛(絕大多數手機用的都是NAND flash,三星的一些手機使用的是OneNAND)。NAND flash具有低成本和高密度的優點。
YAFFS2 是“Yet Another Flash File System, 2nd edition" 的簡稱。 它提供在Linux核心和NAND flash裝置 之前高效率的介面。 YAFFS2並沒有包含在標準的Linux核心中, Google把它新增到了Android的kernel
fs/yaffs2:
New: fs/yaffs2/devextras.h
New: fs/yaffs2/Kconfig
New: fs/yaffs2/Makefile
New: fs/yaffs2/moduleconfig.h
New: fs/yaffs2/yaffs_checkptrw.c
New: fs/yaffs2/yaffs_checkptrw.h
New: fs/yaffs2/yaffs_ecc.c
New: fs/yaffs2/yaffs_ecc.h
New: fs/yaffs2/yaffs_fs.c
New: fs/yaffs2/yaffs_getblockinfo.h
New: fs/yaffs2/yaffs_guts.c
New: fs/yaffs2/yaffs_guts.h
New: fs/yaffs2/yaffsinterface.h
New: fs/yaffs2/yaffs_mtdif1.c
New: fs/yaffs2/yaffs_mtdif1.h
New: fs/yaffs2/yaffs_mtdif2.c
New: fs/yaffs2/yaffs_mtdif2.h
New: fs/yaffs2/yaffs_mtdif.c
New: fs/yaffs2/yaffs_mtdif.h
New: fs/yaffs2/yaffs_nand.c
New: fs/yaffs2/yaffs_nandemul2k.h
New: fs/yaffs2/yaffs_nand.h
New: fs/yaffs2/yaffs_packedtags1.c
New: fs/yaffs2/yaffs_packedtags1.h
New: fs/yaffs2/yaffs_packedtags2.c
New: fs/yaffs2/yaffs_packedtags2.h
New: fs/yaffs2/yaffs_qsort.c
New: fs/yaffs2/yaffs_qsort.h
New: fs/yaffs2/yaffs_tagscompat.c
New: fs/yaffs2/yaffs_tagscompat.h
New: fs/yaffs2/yaffs_tagsvalidity.c
New: fs/yaffs2/yaffs_tagsvalidity.h
New: fs/yaffs2/yportenv.h
Bluetooth -- Google為Bluetooth打上了patch,fix了一些Bluetooth的bug
drivers/bluetooth:
Chg: drivers/bluetooth/bfusb.c
Chg: drivers/bluetooth/bt3c_cs.c
Chg: drivers/bluetooth/btusb.c
Chg: drivers/bluetooth/hci_h4.c
Chg: drivers/bluetooth/hci_ll.c
Scheduler -- 對於Scheduler的改變非常小,我對它並沒有去研究。
Chg: kernel/sched.c
New Android Functionality -- 除了fix一些bug以及其他一些小的更改,Android增加了一些新的功能,介紹如下:
IPC Binder -- The IPC Binder is an Inter-Process Communication (IPC) mechanism. It allows processes to provide services to other processes via a set of higher-level APIs than are available in standard Linux. An Internet search indicated that the Binder concept originated at Be, Inc., and then made its way into Palm's software, before Google wrote a new Binder for Android.
New: drivers/staging/android/binder.c
Low Memory Killer -- Android adds a low-memory killer that, each time it's called, scans the list of running Linux processes, and kills one. It was not clear in our cursory examination why Android adds a low-memory killer on top of the already existing one in the standard Linux kernel.
New: drivers/staging/android/lowmemorykiller.c
Ashmem -- Ashmem is an Anonymous SHared MEMory system that adds interfaces so processes can share named blocks of memory. As an example, the system could use Ashmem to store icons, which multiple processes could then access when drawing their UI. The advantage of Ashmem over traditional Linux shared memory is that it provides a means for the kernel to reclaim these shared memory blocks if they are not currently in use. If a process then tries to access a shared memory block the kernel has freed, it will receive an error, and will then need to reallocate the block and reload the data.
New: mm/ashmem.c
RAM Console and Log Device -- To aid in debugging, Android adds the ability to store kernel log messages to a RAM buffer. Additionally, Android adds a separate logging module so that user processes can read and write user log messages.
New: drivers/staging/android/ram_console.c
Android Debug Bridge -- Debugging embedded devices can best be described as challenging. To make debugging easier, Google created the Android Debug Bridge (ADB), which is a protocol that runs over a USB link between a hardware device running Android and a developer writing applications on a desktop PC.
drivers/usb/gadget:
New: drivers/usb/gadget/android.c
Chg: drivers/usb/gadget/composite.c
Chg: drivers/usb/gadget/f_acm.c
New: drivers/usb/gadget/f_acm.h
New: drivers/usb/gadget/f_adb.c
New: drivers/usb/gadget/f_adb.h
New: drivers/usb/gadget/f_mass_storage.c
New: drivers/usb/gadget/f_mass_storage.h
Android also adds a new real-time clock, switch support, and timed GPIO support. We list the impacted files for these new modules at the end of this document.
Power Management -- Power management is one of the most difficult pieces to get right in mobile devices, so we split it out into a group separate from the other pieces. It's interesting to note that Google added a new power management system to Linux, rather than reuse what already existed. We list the impacted files at the end of this document.
kernel/power:
New: kernel/power/consoleearlysuspend.c
New: kernel/power/earlysuspend.c
New: kernel/power/fbearlysuspend.c
Chg: kernel/power/main.c
Chg: kernel/power/power.h
Chg: kernel/power/process.c
New: kernel/power/userwakelock.c
New: kernel/power/wakelock.c
Miscellaneous Changes -- In addition to the above, we found a number of changes that could best be described as, 'Miscellaneous.' Among other things, these changes include additional debugging support, keypad light controls, and management of TCP networking
http://www.linuxfordevices.com/c ... id-to-a-new-device/
http://hi.baidu.com/smallbigwang/item/95c99ebcb0e9544cba0e1281
也給大家推薦幾門教程:
haolele 發表於 2011-11-11 21:03:34Android系統移植方法詳解
http://www.anzhuoba.com/archiver/?tid-8419.html
[本文WORD文件下載:]
通過Android系統移植,讓它在目標系統上執行起來。Android系統由於用的是linux核心,因此核心移植和嵌入式linux核心移植差異不大,過程如下:
(1)移植boot-loader和linux2.6核心到目標平臺上,讓linux核心可以啟動起來,基本的驅動允許正常。
此過程完全是嵌入式linux的開發,這裡直接跳過。需要注意的是,由於android已經被linux官方開除,因此從
網站上(如http://www.kernel.org/)下載的最新linux核心原始碼已經不包含android的專有驅動,因此建議
從google網上下下載Linux核心,android原始碼瀏覽網站如下:
http://android.git.kernel.org/
從該網站上發現核心相關的包如下:
kernel/common.git 通用android核心專案
kernel/experimental.git 實驗性核心專案
kernel/linux-2.6.git 這個是標準的Linux核心,沒有android的驅動
kernel/lk.git 微核心專案
kernel/msm.git 這個是高通msm7xxx系列晶片所用核心
kernel/omap.git
kernel/tegra.git NVIDIA Tegra系列晶片所用核心
下載核心程式碼的方法如下:
git clone git://android.git.kernel.org/kernel/common.git
下載完後用git branch -a檢視所有git分支,結果如下:
android-2.6.27
origin/HEAD
origin/android-2.6.25
origin/android-2.6.27
origin/android-2.6.29
origin/android-2.6.32
origin/android-2.6.35
origin/android-2.6.36
origin/android-goldfish-2.6.27
origin/android-goldfish-2.6.29
然後切換到最新分支git checkout origin/android-2.6.36
(2)修改核心配置檔案,開啟Android必須的驅動(日誌和BINDER)如下:
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_LOGGER=y
此部分的程式碼在核心drivers/staging/android目錄下。
(3)為了提高啟動速度,採用ramdisk,將android檔案系統的部分內容壓縮到核心中。
首先開啟核心驅動:
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="root"
CONFIG_INITRAMFS_ROOT_UID=0
CONFIG_INITRAMFS_ROOT_GID=0
然後在android原始碼編譯出來的out/target/product/merlin/root目錄複製到核心目錄下。
(4)根據android檔案系統的要求對nand flash進行重新分割槽,舉例如下:
將nand flash分割槽以下8個分割槽
NTIM
OBM
U-boot
Kernel
System
UserData
Mass Storage
BBT
(5)根據分割槽表修改核心啟動引數如下:
CONFIG_CMDLINE="ubi.mtd=4 ubi.mtd=5 ubi.mtd=6 root=ubi0_0 rootfstype=ubifs console=ttyS1,115200 uart_dma init=/init"
引數的意思是:載入的檔案系統部分有3個分割槽,分別為nand flash的第4,5,6分割槽(從0編號),檔案系統採用ubifs格式,控制檯裝置為ttyS1,波特率為115200
啟動的第一個應用程式是/init
(6)確保控制檯的設定和硬體保持一致,如:硬體上串列埠用的是UART1,則核心啟動引數中設定有console=ttyS1,而且android的啟動過程中設要設定正確,修改
部分位於android原始碼system/core/init/init.c檔案中,將
static char *console_name = "/dev/console";
修改成
static char *console_name = "/dev/ttyS1";
(7)修改android原始碼system/core/rootdir目錄下的init.rc檔案,作如下修改(android預設yaffs2檔案系統):
首先將android檔案系統修改成可讀寫,將
mount rootfs rootfs / ro remount
修改成
mount rootfs rootfs / rw remount
然後修改掛載system和userdata部分的程式碼,將
# Mount /system rw first to give the filesystem a chance to save a checkpoint
mount yaffs2 mtd@system /system
mount yaffs2 mtd@system /system ro remount
# We chown/chmod /data again so because mount is run as root + defaults
mount yaffs2 mtd@userdata /data nosuid nodev
chown system system /data
chmod 0771 /data
改成
# Mount /system rw first to give the filesystem a chance to save a checkpoint
mount ubifs ubi0_0 /system ro
# We chown/chmod /data again so because mount is run as root + defaults
mount ubifs ubi1_0 /data nosuid nodev
chown system system /data
chmod 0771 /data
(8)完成後編譯核心,可以啟動檔案系統,控制檯可用,但是沒有顯示啟動log,而且不停的重啟。
(9)系統不停的重啟,因此控制檯已經可用了,自然而然的想到看到logcat日誌,一看,發現logcat裝置居然沒起來,配置檔案裡面都定義了
居然沒起來,檢視了下核心drivers/staging/android目錄,沒有.o檔案,證明是沒編譯到,在看核心目錄下的.config檔案,發現居然沒有了
logcat和binder的巨集定義,配置檔案裡面有定義而.config檔案中無定義,肯定是相關Kconfig檔案的問題,通過分析drivers/staging目錄下的
Kconfig檔案發現是因為STAGING_EXCLUDE_BUILD巨集預設是y,在配置檔案中否定此巨集即可,在配置檔案中CONFIG_STAGING定義後加上即可,如下:
CONFIG_STAGING=y
# CONFIG_STAGING_EXCLUDE_BUILD is not set
修改後重新編譯發現系統完成正常啟動,啟動過程中啟動log也顯示正常。
至此,android初步移植工作已經完成,當然,系統還有很多問題,需要下一步繼續修改。
總結:android的移植按如下流程:
(1)android linux核心的普通驅動移植,讓核心可以在目標平臺上執行起來。
(2)正確掛載檔案系統,確保核心啟動引數和android原始碼system/core/rootdir目錄下的init.rc中的檔案系統掛載正確。
(3)除錯控制檯,讓核心啟動引數中的console引數以及android原始碼system/core/init/init.c中的console_name設定和硬體保持一致
(4)開啟android相關的驅動(logger,binder等),串列埠輸入logcat看logger驅動起來,沒有的話除錯logger驅動。
說明:ARM的核心配置檔案定義在核心arch/arm/configs目錄下。
Android系統移植之按鍵移植本帖最後由 haolele 於 2011-11-11 21:04 編輯
Android系統移植之按鍵移植這一部分主要是移植android的鍵盤和按鍵
(1)Android使用標準的linux輸入事件裝置(/dev/input目錄下)和驅動,按鍵定義在核心include/linux/input.h檔案中,
按鍵定義形式如下:
#define KEY_ESC 1
#define KEY_1 2
#define KEY_2 3
(2)核心中(我的平臺是arch/arm/mach-mmp/merlin.c檔案)中按鍵的定義如下形式:
static struct gpio_keys_button btn_button_table[] = {
= {
.code = KEY_F1,
.gpio = MFP_PIN_GPIO2,
.active_low = 1, /* 0 for down 0, up 1; 1 for down 1, up 0 */
.desc = "H_BTN button",
.type = EV_KEY,
/* .wakeup = */
.debounce_interval = 10, /* 10 msec jitter elimination */
},
= {
.code = KEY_F2,
.gpio = MFP_PIN_GPIO3,
.active_low = 1, /* 0 for down 0, up 1; 1 for down 1, up 0 */
.desc = "O_BTN button",
.type = EV_KEY,
/* .wakeup = */
.debounce_interval = 10, /* 10 msec jitter elimination */
},
= {
.code = KEY_F4,
.gpio = MFP_PIN_GPIO1,
.active_low = 1, /* 0 for down 0, up 1; 1 for down 1, up 0 */
.desc = "S_BTN button",
.type = EV_KEY,
/* .wakeup = */
.debounce_interval = 10, /* 10 msec jitter elimination */
},
};
static struct gpio_keys_platform_data gpio_keys_data = {
.buttons = btn_button_table,
.nbuttons = ARRAY_SIZE(btn_button_table),
};
static struct platform_device gpio_keys = {
.name = "gpio-keys",
.dev = {
.platform_data = &gpio_keys_data,
},
.id = -1,
};
上面定義是將MFP_PIN_GPIO2這個GPIO口的按鍵對映到Linux的KEY_F1按鍵,MPF_PIN_GPIO3對映到KEY_F2,MFP_PIN_GPIO1對映到KEY_F4
(3)上面(2)步實現了從硬體GPIO口到核心標準按鍵的對映,但是android並沒有直接使用對映後的鍵值,而且對其再進行了一次對映,從核心標準鍵值
到android所用鍵值的對映表定義在android檔案系統的/system/usr/keylayout目錄下。標準的對映檔案為qwerty.kl,定義如下:
key 399 GRAVE
key 2 1
key 3 2
key 4 3
key 5 4
key 6 5
key 7 6
key 8 7
key 9 8
key 10 9
key 11 0
key 158 BACK WAKE_DROPPED
key 230 SOFT_RIGHT WAKE
key 60 SOFT_RIGHT WAKE
key 107 ENDCALL WAKE_DROPPED
key 62 ENDCALL WAKE_DROPPED
key 229 MENU WAKE_DROPPED
key 139 MENU WAKE_DROPPED
key 59 MENU WAKE_DROPPED
key 127 SEARCH WAKE_DROPPED
key 217 SEARCH WAKE_DROPPED
key 228 POUND
key 227 STAR
key 231 CALL WAKE_DROPPED
key 61 CALL WAKE_DROPPED
key 232 DPAD_CENTER WAKE_DROPPED
key 108 DPAD_DOWN WAKE_DROPPED
key 103 DPAD_UP WAKE_DROPPED
key 102 HOME WAKE
key 105 DPAD_LEFT WAKE_DROPPED
key 106 DPAD_RIGHT WAKE_DROPPED
key 115 VOLUME_UP
key 114 VOLUME_DOWN
key 116 POWER WAKE
key 212 CAMERA
key 16 Q
key 17 W
key 18 E
key 19 R
key 20 T
key 21 Y
key 22 U
key 23 I
key 24 O
key 25 P
key 26 LEFT_BRACKET
key 27 RIGHT_BRACKET
key 43 BACKSLASH
key 30 A
key 31 S
key 32 D
key 33 F
key 34 G
key 35 H
key 36 J
key 37 K
key 38 L
key 39 SEMICOLON
key 40 APOSTROPHE
key 14 DEL
key 44 Z
key 45 X
key 46 C
key 47 V
key 48 B
key 49 N
key 50 M
key 51 COMMA
key 52 PERIOD
key 53 SLASH
key 28 ENTER
key 56 ALT_LEFT
key 100 ALT_RIGHT
key 42 SHIFT_LEFT
key 54 SHIFT_RIGHT
key 15 TAB
key 57 SPACE
key 150 EXPLORER
key 155 ENVELOPE
key 12 MINUS
key 13 EQUALS
key 215 AT
(4)android對底層按鍵的處理方法
android按鍵的處理是Window Manager負責,主要的對映轉換實現在android原始碼frameworks/base/libs/ui/EventHub.cpp
此檔案處理來自底層的所有輸入事件,並根據來源對事件進行分類處理,對於按鍵事件,處理過程如下:
(a)記錄驅動名稱為
(b)獲取環境變數ANDROID_ROOT為系統路徑(預設是/system,定義在android原始碼/system/core/rootdir/init.rc檔案中)
(c)查詢路徑為"系統路徑/usr/keylayout/驅動名稱.kl"的按鍵對映檔案,如果不存在則預設用路徑為"系統路徑/usr/keylayout/qwerty.kl"
這個預設的按鍵對映檔案,對映完成後再把經對映得到的android按鍵碼值發給上層應用程式。
所以我們可以在核心中定義多個按鍵裝置,然後為每個裝置設定不同的按鍵對映檔案,不定義則會預設用qwerty.kl
(5)舉例
上面(2)步我們在核心中宣告瞭一個名為"gpio-keys"的按鍵裝置,此裝置定義在核心drivers/input/keyboard/gpio_keys.c檔案中
然後我們在核心啟動過程中註冊此裝置: platform_device_register(&gpio_keys);
然後我們可以自己定義一個名為gpio-keys.kl的android按鍵對映檔案,此檔案的定義可以參考querty.kl的內容,比如說我們想將MPF_PIN_GPIO3
對應的按鍵作android中的MENU鍵用,首先我們在核心中將MPF_PIN_GPIO3對映到KEY_F2,在核心include/linux/input.h中查詢KEY_F2發現
#define KEY_F2 60
參照KEY_F2的值我們在gpio-keys.kl中加入如下對映即可
key 60 MENU WAKE
其它按鍵也照此新增,完成後將按鍵表放置到/system/usr/keylayout目錄下即可。
補充:
(1)android按鍵裝置的對映關係可以在logcat開機日誌中找的到(查詢EventHub即可)
(2)android按鍵裝置由Window Manager負責,Window Manager從按鍵驅動讀取核心按鍵碼,然後將核心按鍵碼轉換成android按鍵碼,轉換完成
後Window Manager會將核心按鍵碼和android按鍵碼一起發給應用程式來使用,這一點一定要注意。Android系統開發小知識-在android產品開 發中新增新的編譯模組 Android開發中使用者內容定義在vendor目錄下,而使用者產品的內容都定義在vendor/<company_name> /<board_name>目錄下
如果需要新增新的內容,可以在該目錄下新建子目錄,同時修改AndroidBoard.mk檔案即可。比如說要新增一個按鍵對映檔案:
(1)在vendor/<company_name>/<board_name>目錄下建立一個keymaps子目錄
(2)將我們需要的按鍵對映檔案gpio-keys.kl和power-button.kl複製到keymaps目錄下
(3)在keymaps目錄下新建一個Mdroid.mk檔案,內容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
file := $(TARGET_OUT_KEYLAYOUT)/gpio-keys.kl
ALL_PREBUILT += $(file)
$(file): $(LOCAL_PATH)/gpio-keys.kl | $(ACP)
$(transform-prebuilt-to-target)
file := $(TARGET_OUT_KEYLAYOUT)/power-button.kl
ALL_PREBUILT += $(file)
$(file): $(LOCAL_PATH)/power-button.kl | $(ACP)
$(transform-prebuilt-to-target)
(4)在vendor/<company_name>/<board_name>目錄下的AndroidBoard.mk新增如下內容:
include $(LOCAL_PATH)/keymaps/Mdroid.mk
haolele 發表於 2011-11-11 21:04:44
Android系統移植之按鍵字元表本帖最後由 haolele 於 2011-11-11 21:05 編輯
Android系統移植之按鍵字元表
上節講android的Window Manager將核心按鍵碼通過按鍵對映錶轉換成android按鍵碼,
這節講的是android按鍵碼向android字元的轉換,轉換也是通過Window Manager來完成的
(1)原始按鍵字元表,我們知道一個按鍵是可以顯示多個字元的,決定顯示字元的是CAPS(大小寫),FN,NUNMBER等按鍵
舉例如下:
# keycode display number base caps fn caps_fn
A 'A' '2' 'a' 'A' '#' 0x00
B 'B' '2' 'b' 'B' '<' 0x00
C 'C' '2' 'c' 'C' '9' 0x00E7
D 'D' '3' 'd' 'D' '5' 0x00
E 'E' '3' 'e' 'E' '2' 0x0301
F 'F' '3' 'f' 'F' '6' 0x00A5
G 'G' '4' 'g' 'G' '-' '_'
H 'H' '4' 'h' 'H' '[' '{'
I 'I' '4' 'i' 'I' '$' 0x0302
J 'J' '5' 'j' 'J' ']' '}'
K 'K' '5' 'k' 'K' '"' '~'
L 'L' '5' 'l' 'L' ''' '`'
M 'M' '6' 'm' 'M' '!' 0x00
N 'N' '6' 'n' 'N' '>' 0x0303
O 'O' '6' 'o' 'O' '(' 0x00
P 'P' '7' 'p' 'P' ')' 0x00
Q 'Q' '7' 'q' 'Q' '*' 0x0300
R 'R' '7' 'r' 'R' '3' 0x20AC
S 'S' '7' 's' 'S' '4' 0x00DF
T 'T' '8' 't' 'T' '+' 0x00A3
U 'U' '8' 'u' 'U' '&' 0x0308
V 'V' '8' 'v' 'V' '=' '^'
W 'W' '9' 'w' 'W' '1' 0x00
X 'X' '9' 'x' 'X' '8' 0xEF00
Y 'Y' '9' 'y' 'Y' '%' 0x00A1
Z 'Z' '9' 'z' 'Z' '7' 0x00
# on pc keyboards
COMMA ',' ',' ',' ';' ';' '|'
PERIOD '.' '.' '.' ':' ':' 0x2026
AT '@' '0' '@' '0' '0' 0x2022
SLASH '/' '/' '/' '?' '?' '\'
SPACE 0x20 0x20 0x20 0x20 0xEF01 0xEF01
ENTER 0xa 0xa 0xa 0xa 0xa 0xa
TAB 0x9 0x9 0x9 0x9 0x9 0x9
0 '0' '0' '0' ')' ')' ')'
1 '1' '1' '1' '!' '!' '!'
2 '2' '2' '2' '@' '@' '@'
3 '3' '3' '3' '#' '#' '#'
4 '4' '4' '4' '$' '$' '$'
5 '5' '5' '5' '%' '%' '%'
6 '6' '6' '6' '^' '^' '^'
7 '7' '7' '7' '&' '&' '&'
8 '8' '8' '8' '*' '*' '*'
9 '9' '9' '9' '(' '(' '('
GRAVE '`' '`' '`' '~' '`' '~'
MINUS '-' '-' '-' '_' '-' '_'
EQUALS '=' '=' '=' '+' '=' '+'
LEFT_BRACKET '[' '[' '[' '{' '[' '{'
RIGHT_BRACKET ']' ']' ']' '}' ']' '}'
BACKSLASH '\' '\' '\' '|' '\' '|'
SEMICOLON ';' ';' ';' ':' ';' ':'
APOSTROPHE ''' ''' ''' '"' ''' '"'
STAR '*' '*' '*' '*' '*' '*'
POUND '#' '#' '#' '#' '#' '#'
PLUS '+' '+' '+' '+' '+' '+'
(2)android為了減少載入時間,並沒有使用原始按鍵表檔案,而是將其轉換成二進位制檔案
轉換的工具原始碼在android原始碼build/tools/kcm目錄下,android在編譯過程中會
首先編譯轉換工具,然後利用轉換工具將android原始碼sdk/emulator/keymaps目錄下
的qwerty.kcm和qwerty2.kcm檔案分別轉換成qwerty.kcm.bin和qwerty2.kcm.bin
轉換後的二進位制檔案複製到out/target/product/<board_name>/system/usr/keychars
目錄下,也就是目標平臺的/system/usr/keychars目錄中。
(3)Window Manager對按鍵的處理在android原始碼frameworks/base/libs/ui/EventHub.cpp檔案中
Window Manager從核心接收到一個按鍵輸入事件後會首先呼叫按鍵對映表將核心按鍵碼對映成android按鍵碼(這部分上節已講),然後會
將android按鍵碼轉換成字元,具體過程如下:
(a)設定系統系統屬性hw.keyboards.裝置號.devname的值為裝置名
以上節的gpio-keys裝置為例,會設定系統屬性hw.keyboards.65539.devname的值為gpio-keys
(b)載入按鍵字元表,首先載入/system/usr/keychars目錄下的裝置名.kcm.bin檔案(此例即gpio-keys.kcm.bin檔案),如果載入失敗
則載入該目錄下的querty.kcm.bin.
(c)利用載入的按鍵字元表將android按鍵轉換成按鍵字元發給上層應用程式。
(4)一般情況下一個控制按鍵是不需要作按鍵字元表的,系統會呼叫預設的去處理,但是如果要開發一個全功能鍵盤(包含了字母和數字),那可能就需要
自己作一個專用的按鍵字元表了。android系統開發小問題-啟動過程中android字元沒有顯示出來 android目標平臺可以正常啟動,但是啟動過程中的android字元沒有顯示出來,這個是linux核心配置的問題
開啟核心framebuffer控制檯即可。
(1)make menuconifg後選擇Device Drivers->Graphics support->Console display driver support->Framebuffer Console support
然後開啟相關的幾個配置選項即可。
(2)直接修改核心配置檔案,如下:
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
CONFIG_FONT_6x11=y
# CONFIG_FONT_7x14 is not set
# CONFIG_FONT_PEARL_8x8 is not set
# CONFIG_FONT_ACORN_8x8 is not set
# CONFIG_FONT_MINI_4x6 is not set
# CONFIG_FONT_SUN8x16 is not set
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_10x18 is not set
(3)android啟動過程中的android字元顯示在原始碼的system/core/init.c中,如下:
if( load_565rle_image(INIT_IMAGE_FILE) ) {
fd = open("/dev/tty0", O_WRONLY);
if (fd >= 0) {
const char *msg;
msg = "\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n" // console is 40 cols x 30 lines
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
" A N D R O I D ";
write(fd, msg, strlen(msg));
close(fd);
}
}
haolele 發表於 2011-11-11 21:06:22
Android系統開發之觸控式螢幕tslib移植(核心)和原理分析本帖最後由 haolele 於 2011-11-11 21:07 編輯
Android系統開發之觸控式螢幕tslib移植(核心)和原理分析
首先了解一下tslib的執行原理,tslib的執行分成兩部分
(1)校驗
在LCD固定座標位置依次顯示出5個座標讓使用者觸控,把LCD座標和使用者觸控時驅動屏驅動底層的座標總共5組值儲存起來
執行tslib庫的演算法對其進行運算,得出校準用7個值
(2)校準
每次觸控式螢幕驅動讀取到硬體座標時應用校準用的7個值對該座標進行一次運算,然後將運算後的座標作為正常座標即可。
按照上面的原理,
(1)我們先修改核心部分,我的平臺用的觸控螢幕驅動是tsc2007,驅動檔案為核心/drivers/input/touchscreen
目錄下的tsc2007.c和ts_linear.c
其中,ts_linear.c中定義的是校準模組,該模組在proc檔案系統中建立了7個檔案,用來存放校準用的7個點,7的點的預設值
為1,0,0,0,1,0,1,對應的目標平臺檔案系統的位置為/proc/sys/dev/ts_device目錄下a0,a1,a2,a3,a4,a5,a6等7個檔案
此模組中還定義了一個校準函式ts_linear_scale,此函式的主要內容是讀取a0,a1,a2,a3,a4,a5,a6等7個檔案中的值作為7個
校準值與傳入的觸控平座標值進行運算,返回運算結果。
ts_linear_scale函式定義如下:
int ts_linear_scale(int *x, int *y, int swap_xy)
{
int xtemp, ytemp;
xtemp = *x;
ytemp = *y;
if (cal.a == 0)
return -EINVAL;
*x = (cal.a + cal.a * xtemp + cal.a * ytemp) / cal.a;
*y = (cal.a + cal.a * xtemp + cal.a * ytemp) / cal.a;
if (swap_xy) {
int tmp = *x;
*x = *y;
*y = tmp;
}
return 0;
}ts2007.c為觸控式螢幕驅,與其他驅動不同的地方是在取得硬體座標值傳送之前先呼叫了ts_linear_scale函式對座標值進行了校準
if (x > 0 && y > 0)
{
ts_linear_scale(&x, &y, invert);
input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y);
input_report_abs(input, ABS_PRESSURE, 255);
input_report_abs(input, ABS_TOOL_WIDTH, 1);
input_report_key(input, BTN_TOUCH, 1);
input_sync(input);
}
(2)在android原始碼/system/core/rootdir/init.rc檔案中新增tslib相關的巨集定義如下:
# touchscreen parameters
export TSLIB_FBDEVICE /dev/graphics/fb0
export TSLIB_CALIBFILE /data/etc/pointercal
export TSLIB_CONFFILE /system/etc/ts.conf
export TSLIB_TRIGGERDEV /dev/input/event0
export TSLIB_TSDEVICE /dev/input/event1
(2)移植tslib庫到android系統,比較麻煩,看下一節的內容。
(3)校驗程式完成後會將生成的7個校準值寫入到環境變數TSLIB_CALIBFILE對應的路徑/data/etc/pointercal檔案中
(4)校驗完後將pointercal檔案中的7個值分別寫入到/proc/sys/dev/ts_device目錄下a0,a1,a2,a3,a4,a5,a6檔案即可。
(5)開機啟動的時候我們編寫一個應用程式,首先判斷環境變數TSLIB_CALIBFILE對應的路徑/data/etc/pointercal檔案是否存在,如果
檔案存在而且非空,則將該檔案中的7個值取出來分別寫入到/proc/sys/dev/ts_device目錄下a0,a1,a2,a3,a4,a5,a6檔案
(6)為了確保未校驗前觸控式螢幕可用,我們將一次校驗後得出的7個座標值作為初始值,修改到核心ts_linear.c檔案中。下面是原始碼:
ts_linear.c檔案
/*
* Touchscreen Linear Scale Adaptor
*
* Copyright (C) 2009 Marvell Corporation
*
* Author: Mark F. Brown <markb@marvell.com>
* Based on tslib 1.0 plugin linear.c by Russel King
*
* This library is licensed under GPL.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/sysctl.h>
#include <asm/system.h>
/*
* sysctl-tuning infrastructure.
*/
static struct ts_calibration {
/* Linear scaling and offset parameters for x,y (can include rotation) */
int a;
} cal;
static ctl_table ts_proc_calibration_table[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "a0",
.data = &cal.a,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "a1",
.data = &cal.a,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "a2",
.data = &cal.a,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "a3",
.data = &cal.a,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "a4",
.data = &cal.a,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "a5",
.data = &cal.a,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "a6",
.data = &cal.a,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &proc_dointvec,
},
{.ctl_name = 0}
};
static ctl_table ts_proc_root[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "ts_device",
.mode = 0555,
.child = ts_proc_calibration_table,
},
{.ctl_name = 0}
};
static ctl_table ts_dev_root[] = {
{
.ctl_name = CTL_DEV,
.procname = "dev",
.mode = 0555,
.child = ts_proc_root,
},
{.ctl_name = 0}
};
static struct ctl_table_header *ts_sysctl_header;
int ts_linear_scale(int *x, int *y, int swap_xy)
{
int xtemp, ytemp;
xtemp = *x;
ytemp = *y;
if (cal.a == 0)
return -EINVAL;
*x = (cal.a + cal.a * xtemp + cal.a * ytemp) / cal.a;
*y = (cal.a + cal.a * xtemp + cal.a * ytemp) / cal.a;
if (swap_xy) {
int tmp = *x;
*x = *y;
*y = tmp;
}
return 0;
}
EXPORT_SYMBOL(ts_linear_scale);
static int __init ts_linear_init(void)
{
ts_sysctl_header = register_sysctl_table(ts_dev_root);
/* Use default values that leave ts numbers unchanged after transform */
cal.a = 1;
cal.a = 0;
cal.a = 0;
cal.a = 0;
cal.a = 1;
cal.a = 0;
cal.a = 1;
return 0;
}
static void __exit ts_linear_cleanup(void)
{
unregister_sysctl_table(ts_sysctl_header);
}
module_init(ts_linear_init);
module_exit(ts_linear_cleanup);
MODULE_DESCRIPTION("touch screen linear scaling driver");
MODULE_LICENSE("GPL");
ts2007.c檔案
/*
* linux/drivers/input/touchscreen/tsc2007.c
*
* touch screen driver for tsc2007
*
* Copyright (C) 2006, Marvell Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/freezer.h>
#include <linux/proc_fs.h>
#include <linux/clk.h>
#include <linux/i2c.h>
#include <mach/gpio.h>
#include <linux/sysctl.h>
#include <asm/system.h>
extern int ts_linear_scale(int *x, int *y, int swap_xy);
/* Use MAV filter */
#define TSC_CMD_SETUP 0xb0
/* Use 12-bit */
#define TSC_CMD_X 0xc0
#define TSC_CMD_PLATEX 0x80
#define TSC_CMD_Y 0xd0
#define TSC_CMD_PLATEY 0x90
#define TSC_X_MAX 4096
#define TSC_Y_MAX 4096
#define TSC_X_MIN 0
#define TSC_Y_MIN 0
/* delay time for compute x, y, computed as us */
#define DEBUG
#ifdef DEBUG
#define TS_DEBUG(fmt,args...) printk(KERN_DEBUG fmt, ##args )
#else
#define TS_DEBUG(fmt,args...)
#endif
static int x_min=TSC_X_MIN;
static int y_min=TSC_Y_MIN;
static int x_max=TSC_X_MAX;
static int y_max=TSC_Y_MAX;
static int invert = 0;
static int debounce_time = 150;
static int init_debounce = true;
static int delay_time = 1;
enum tsc2007_status {
PEN_UP,
PEN_DOWN,
};
struct _tsc2007 {
struct input_dev *dev;
int x; /* X sample values */
int y; /* Y sample values */
int status;
struct work_struct irq_work;
struct i2c_client *client;
unsigned long last_touch;
};
struct _tsc2007 *g_tsc2007;
/* update abs params when min and max coordinate values are set */
int tsc2007_proc_minmax(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
struct _tsc2007 *tsc2007= g_tsc2007;
struct input_dev *input = tsc2007->dev;
/* update value */
int ret = proc_dointvec(table, write, filp, buffer, lenp, ppos);
/* updated abs params */
if (input) {
TS_DEBUG(KERN_DEBUG "update x_min %d x_max %d"
" y_min %d y_max %d\n", x_min, x_max,
y_min, y_max);
input_set_abs_params(input, ABS_X, x_min, x_max, 0, 0);
input_set_abs_params(input, ABS_Y, y_min, y_max, 0, 0);
}
return ret;
}
static ctl_table tsc2007_proc_table[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "x-max",
.data = &x_max,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &tsc2007_proc_minmax,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "y-max",
.data = &y_max,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &tsc2007_proc_minmax,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "x-min",
.data = &x_min,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &tsc2007_proc_minmax,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "y-min",
.data = &y_min,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &tsc2007_proc_minmax,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "invert_xy",
.data = &invert,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "debounce_time",
.data = &debounce_time,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = CTL_UNNUMBERED,
.procname = "delay_time",
.data = &delay_time,
.maxlen = sizeof(int),
.mode = 0666,
.proc_handler = &proc_dointvec,
},
{ .ctl_name = 0 }
};
static ctl_table tsc2007_proc_root[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "ts_device",
.mode = 0555,
.child = tsc2007_proc_table,
},
{ .ctl_name = 0 }
};
static ctl_table tsc2007_proc_dev_root[] = {
{
.ctl_name = CTL_DEV,
.procname = "dev",
.mode = 0555,
.child = tsc2007_proc_root,
},
{ .ctl_name = 0 }
};
static struct ctl_table_header *sysctl_header;
static int __init init_sysctl(void)
{
sysctl_header = register_sysctl_table(tsc2007_proc_dev_root);
return 0;
}
static void __exit cleanup_sysctl(void)
{
unregister_sysctl_table(sysctl_header);
}
static int tsc2007_measure(struct i2c_client *client, int *x, int * y)
{
u8 x_buf = {0, 0};
u8 y_buf = {0, 0};
i2c_smbus_write_byte(client, TSC_CMD_PLATEX);
msleep_interruptible(delay_time);
i2c_smbus_write_byte(client, TSC_CMD_X);
i2c_master_recv(client, x_buf, 2);
*x = (x_buf<<4) | (x_buf >>4);
i2c_smbus_write_byte(client, TSC_CMD_PLATEY);
msleep_interruptible(delay_time);
i2c_smbus_write_byte(client, TSC_CMD_Y);
i2c_master_recv(client, y_buf, 2);
*y = (y_buf<<4) | (y_buf >>4);
*y = 4096 - *y; //added by allen
printk("\ntouchscreen x = 0x%x, y = 0x%x\n",*x,*y);
return 0;
}
static void tsc2007_irq_work(struct work_struct *work)
{
struct _tsc2007 *tsc2007= g_tsc2007;
struct i2c_client *client = tsc2007-> client;
struct input_dev *input = tsc2007->dev;
int x = -1, y = -1, is_valid = 0;
int tmp_x = 0, tmp_y = 0;
int gpio = irq_to_gpio(client->irq);
/* Ignore if PEN_DOWN */
if(PEN_UP == tsc2007->status){
if (gpio_request(gpio, "tsc2007 touch detect")) {
printk(KERN_ERR "Request GPIO failed, gpio: %X\n", gpio);
return;
}
gpio_direction_input(gpio);
while(0 == gpio_get_value(gpio)){
if ((jiffies_to_msecs(
((long)jiffies - (long)tsc2007->last_touch)) <
debounce_time &&
tsc2007->status == PEN_DOWN) ||
init_debounce)
{
init_debounce = false;
tsc2007_measure(client, &tmp_x, &tmp_y);
TS_DEBUG(KERN_DEBUG
"dropping pen touch %lu %lu (%u)\n",
jiffies, tsc2007->last_touch,
jiffies_to_msecs(
(long)jiffies - (long)tsc2007->last_touch));
schedule();
continue;
}
/* continue report x, y */
if (x > 0 && y > 0)
{
ts_linear_scale(&x, &y, invert);
input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y);
input_report_abs(input, ABS_PRESSURE, 255);
input_report_abs(input, ABS_TOOL_WIDTH, 1);
input_report_key(input, BTN_TOUCH, 1);
input_sync(input);
}
tsc2007->status = PEN_DOWN;
tsc2007_measure(client, &x, &y);
TS_DEBUG(KERN_DEBUG "pen down x=%d y=%d!\n", x, y);
is_valid = 1;
schedule();
}
if (is_valid)
{
/*consider PEN_UP */
tsc2007->status = PEN_UP;
input_report_abs(input, ABS_PRESSURE, 0);
input_report_abs(input, ABS_TOOL_WIDTH, 1);
input_report_key(input, BTN_TOUCH, 0);
input_sync(input);
tsc2007->last_touch = jiffies;
TS_DEBUG(KERN_DEBUG "pen up!\n");
}
gpio_free(gpio);
}
}
static irqreturn_t tsc2007_interrupt(int irq, void *dev_id)
{
schedule_work(&g_tsc2007->irq_work);
return IRQ_HANDLED;
}
static int __devinit tsc2007_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct _tsc2007 *tsc2007;
struct input_dev *input_dev;
int ret;
tsc2007 = kzalloc(sizeof(struct _tsc2007), GFP_KERNEL);
input_dev = input_allocate_device();
g_tsc2007 = tsc2007;
if (!tsc2007 || !input_dev) {
ret = -ENOMEM;
goto fail1;
}
i2c_set_clientdata(client, tsc2007);
tsc2007->dev = input_dev;
input_dev->name = "tsc2007";
input_dev->phys = "tsc2007/input0";
//input_dev->id.bustype = BUS_HOST;
input_dev->dev.parent = &client->dev;
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(ABS_PRESSURE, input_dev->evbit);
__set_bit(ABS_X, input_dev->evbit);
__set_bit(ABS_Y, input_dev->evbit);
input_set_abs_params(input_dev, ABS_X, x_min, x_max, 0, 0);
input_set_abs_params(input_dev, ABS_Y, y_min, y_max, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
ret = request_irq(client->irq, tsc2007_interrupt,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
"tsc2007 irq", NULL);
if (ret){
printk(KERN_ERR "tsc2007 request irq failed\n");
goto fail2;
}
ret = input_register_device(tsc2007->dev);
if (ret){
printk(KERN_ERR "tsc2007 register device fail\n");
goto fail2;
}
/*init */
tsc2007->status = PEN_UP;
tsc2007->client = client;
tsc2007->last_touch = jiffies;
INIT_WORK(&tsc2007->irq_work, tsc2007_irq_work);
/* init tsc2007 */
i2c_smbus_write_byte(client, TSC_CMD_SETUP);
return 0;
fail2:
free_irq(client->irq, client);
fail1:
i2c_set_clientdata(client, NULL);
input_free_device(input_dev);
kfree(tsc2007);
return ret;
}
static int __devexit tsc2007_remove(struct i2c_client *client)
{
struct _tsc2007 *tsc2007 = i2c_get_clientdata(client);
if(client->irq)
free_irq(client->irq, client);
i2c_set_clientdata(client, NULL);
input_unregister_device(tsc2007->dev);
kfree(tsc2007);
return 0;
}
static struct i2c_device_id tsc2007_idtable[] = {
{ "tsc2007", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tsc2007_idtable);
static struct i2c_driver tsc2007_driver = {
.driver = {
.name = "tsc2007",
},
.id_table = tsc2007_idtable,
.probe = tsc2007_probe,
.remove = __devexit_p(tsc2007_remove),
};
static int __init tsc2007_ts_init(void)
{
init_sysctl();
return i2c_add_driver(&tsc2007_driver);
}
static void __exit tsc2007_ts_exit(void)
{
cleanup_sysctl();
i2c_del_driver(&tsc2007_driver);
}
module_init(tsc2007_ts_init);
module_exit(tsc2007_ts_exit);
MODULE_DESCRIPTION("tsc2007 touch screen driver");
MODULE_LICENSE("GPL");
haolele 發表於 2011-11-11 21:07:48
Android系統開發之tslib移植本帖最後由 haolele 於 2011-11-11 21:08 編輯
Android系統開發之tslib移植
(1)切換至tslib目錄然後執行如下命令(以marvell平臺為例)
./autogen.sh
echo "ac_cv_func_malloc_0_nonnull=yes" > arm-marvell-linux.cache
./configure --host=arm-marvell-linux-gnueabi --prefix=/work/svn/ts_build --cache-file=arm-marvell-linux.cache
上面三步僅僅是為了取得tslib目錄下的config.h檔案
(2)將tslib複製到android原始碼vendor/<company_name>/<board_name>目錄下
(3)修改vendor/<company_name>/<board_name>目錄下的AndroidBoard.mk檔案,加入如下內容
include $(LOCAL_PATH)/tslib/Mdroid.mk
一定要主義LOCAL_PATH這個巨集的時效性
(4)在tslib目錄下建立Mdroid.mk,內容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
TS_PATH := $(LOCAL_PATH)
include $(TS_PATH)/src/Mdroid.mk
include $(TS_PATH)/plugins/Mdroid.mk
include $(TS_PATH)/tests/Mdroid.mk
include $(CLEAR_VARS)
file := $(TARGET_OUT_ETC)/ts.conf
$(file) : $(TS_PATH)/etc/ts.conf | $(ACP)
$(transform-prebuilt-to-target)
ALL_PREBUILT += $(file)
(5)在tslib/src目錄下建立Mdroid.mk,內容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= ts_attach.c ts_close.c ts_config.c \
ts_error.c ts_fd.c ts_load_module.c ts_open.c ts_parse_vars.c \
ts_read.c ts_read_raw.c ts_option.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../
LOCAL_SHARED_LIBRARIES += libutils libcutils
LOCAL_SHARED_LIBRARIES += libdl
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libts
include $(BUILD_SHARED_LIBRARY)
(6)在tslib/plugins目錄下建立Mdroid.mk,內容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= input-raw.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../ \
$(LOCAL_PATH)/../src
LOCAL_SHARED_LIBRARIES := libts
LOCAL_MODULE := input
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= pthres.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../ \
$(LOCAL_PATH)/../src
LOCAL_SHARED_LIBRARIES := libts
LOCAL_MODULE := pthres
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= variance.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../ \
$(LOCAL_PATH)/../src
LOCAL_SHARED_LIBRARIES := libts
LOCAL_MODULE := variance
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= dejitter.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../ \
$(LOCAL_PATH)/../src
LOCAL_SHARED_LIBRARIES := libts
LOCAL_MODULE := dejitter
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= linear.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../ \
$(LOCAL_PATH)/../src
LOCAL_SHARED_LIBRARIES := libts
LOCAL_MODULE := linear
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
(7)在tslib/tests目錄下建立Mdroid.mk,內容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= ts_calibrate.c fbutils.c testutils.c font_8x8.c font_8x16.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../ \
$(LOCAL_PATH)/../src
LOCAL_SHARED_LIBRARIES := libts
LOCAL_SHARED_LIBRARIES += libutils libcutils
LOCAL_MODULE := tscalibrate
include $(BUILD_EXECUTABLE)
(8)在tslib/config.h檔案中加入如下定義:
#define TS_CONF "/system/etc/ts.conf"
#define PLUGIN_DIR "/system/lib"
#define TS_POINTERCAL "/data/etc/pointercal"
(9)將下面路徑檔案
tslib/src/ts_open.c
tslib/tests/ts_calibrate.c
tslib/tests/fbutils.c
中的
#include <sys/fcntl.h>
修改成
#include <fcntl.h>
(10)將tslib/tests/ts_calibrate.c檔案中
static int clearbuf(struct tsdev *ts)
修改為
static void clearbuf(struct tsdev *ts)
(11)修改tslib/etc/ts.conf內容如下:
module_raw input
module pthres pmin=1
module variance delta=30
module dejitter delta=100
module linear
(12)在android原始碼init.rc中宣告tslib相關的巨集如下:
# touchscreen parameters
export TSLIB_FBDEVICE /dev/graphics/fb0
export TSLIB_CALIBFILE /data/etc/pointercal
export TSLIB_CONFFILE /system/etc/ts.conf
export TSLIB_TRIGGERDEV /dev/input/event0
export TSLIB_TSDEVICE /dev/input/event1
(13)重新編譯後即可呼叫tscalibrate命令來校驗觸控式螢幕,校驗後產生一個/data/etc/pointercal檔案。
文末彩蛋:
1.CSDN學院助學會員:僅需百元- 1300門課+600次下載特權,一次購買,全年無憂!點選檢視。
2.CSDN學院知識週刊:每週更新學院優惠課程活動及精品上新內容,點選檢視!
3.本期推薦linux課程:
課程名稱 | 課程連結 | 技術分類 |
Linux視訊教程 | https://edu.csdn.net/course/detail/9128?utm_source=blog11xk | 系統/網路/運維 > Linux |
zabbix企業實戰應用 | https://edu.csdn.net/course/detail/9124?utm_source=blog11xk | 系統/網路/運維 > Linux |
Linux 實用講解+實操+面試題 | https://edu.csdn.net/course/detail/9116?utm_source=blog11xk | 系統/網路/運維 > Linux |
相關文章
- “菜鳥”程式設計師和“大神”程式設計師差距在哪裡程式設計師
- Java集合從菜鳥到大神演變Java
- linux學習導讀_鳥哥的私房菜Linux
- 成為高手的必經之路——學會除錯程式碼(菜鳥必讀)除錯
- Linux“菜鳥”到“菜鳥的一些建議Linux
- 菜鳥的讀書筆記筆記
- Linux菜鳥到老鳥的那些建議Linux
- 鳥哥的 Linux 私房菜Linux
- 菜鳥也裝Linux(轉)Linux
- 「Linux」鳥叔私房菜第五章讀書筆記Linux筆記
- 無論是菜鳥還是高手,這招PDF轉Word技巧必須Get
- 鳥哥的Linux私房菜--CPU種類Linux
- 菜鳥學資料庫(五)——MySQL必備命令資料庫MySql
- 月薪3000跟月薪3萬的人都有什麼區別?原來差距在這裡
- 菜鳥學Java(十一)——GET與POSTJava
- 月薪8K與月薪3W的程式設計師原來差距到底在哪裡?程式設計師
- 鳥哥的Linux私房菜 -- 電子書(pdf)Linux
- Android菜鳥學習js筆記一AndroidJS筆記
- 劉遄:作為一名新人讀完《鳥哥的Linux私房菜》的感想Linux
- 【菜鳥讀原始碼】halo✍原始碼學習 (一)原始碼
- IT菜鳥的學習生活
- 零基礎轉行Python難嗎?這裡有從Python新人菜鳥到大神的超全教程分享Python
- Linux菜鳥入門級命令大全(轉)Linux
- 菜鳥入門:Linux之Makefile概述(轉)Linux
- 分享實用乾貨:辦公必備的6個軟體,大神都在用!
- 月薪8k 和 月薪38K的程式設計師差距在哪裡?程式設計師
- 【同行說技術】Android從小白到大神必讀資料彙總(二)Android
- 關於知識圖譜,各路大神最近都在讀哪些論文?
- 小白必備,5個超實用的自媒體工具,運營大神都在用
- 標頭檔案與庫檔案與菜鳥 (轉)
- PJzhang:鳥哥的linux私房菜-shell指令碼-上Linux指令碼
- linux-鳥哥私房菜學習筆記Linux筆記
- 菜鳥理解的區塊鏈區塊鏈
- 菜鳥的架構師之路架構
- 核心菜鳥的成長之路
- 菜鳥的Node.js之旅Node.js
- 菜鳥看前端(Git)前端Git
- java菜鳥入門Java