A. 【Camera專題】Camera驅動源碼全解析_下
1、手把手擼一份驅動 到 點亮 Camera
2、Camera dtsi 完全解析
3、Camera驅動源碼全解析上
4、Camera驅動源碼全解析下
上篇文章分析了C文件函數的實現,本文繼續分析h文件的配置信息。
推薦文章:
MIPI CSI2學習(一):說一說MIPI CSI2
高通camera驅動分析
參照sensor規格書或者咨詢fae,配置:
2.1 sensor幀的輸出和關閉
sensor以流的方式 輸出幀.
2.2 開啟sensor 端的group 功能
開啟sensor 端的group 功能,將曝光(line),gain等打包,保證在同一幀進去生效
2.3 sensor嵌入式數據
2.4 sensor初始化相關寄存器
2.5 sensor解析度相關寄存器
以上的sensor寄存器配置一般有fae廠商提供,驅動工程師盡可能的掌握相關寄存器代表的含義。
如控制寬高、幀率、曝光等等寄存器
我們只用到16位,因此
sensor_id_reg_addr = 0x300b,
sensor_id = 0x0D42,
曝光時間以行長為單位; PCLK以Hz為單位;
行長以周期數為單位,幀長以行長數為單位;其中周期數就是頻率
T 周期以ms為單位;
f 頻率以Hz為單位;
f = 1 / T;
可以參考這篇文章:
camera曝光和幀率_songqiangzmt的博客
比如這里又3個寄存器,每個寄存器是8bit:
max_linecount = 0x ff ff -8
暫時沒弄清楚
這里指的是暗電流值,
一般來說 raw8 都是 16, raw10為 16x4=64, raw12 =16x4x4
感測器可以流式傳輸許多不同的 數據類型(DT) 。
該數據被包裝在不同的流中。 在一個流中,可以有一個或多個不同的DT。 一種 虛擬通道(VC) 分配給每個流。 DT和VC的組合應為唯一,並分配了一個通道ID(CID)。
有關如何指定CID的要求/限制。 當前的MIPI CSI_Rx支持四個VC,每個VC最多可以有四個CID,如下表所示。
感測器可能具有內置的pattern generator。 通過設置專用寄存器,感測器可以將生成的圖案輸出。
當出現圖像異常時,可以使用此功能看看sensor本身輸出是否有問題。
binning_factor主要是用來控制拍照亮度跟預覽亮度一致的,當然也可以解決預覽噪點過大的問題!
3A演算法里,曝光時間 snap_exp_time *= (float)(binning_multiplier);
3A源碼
賦值源碼
關鍵日誌:
CSI :Camera Serial Interface 定義了一個位於處理器和攝像模組之間的高速串列介面
為使CSI_Tx(感測器)和CRI_Rx(設備)正常工作,需要一段時間它們之間需要同步。
此時間在此處設置為計時器時鍾滴答數。 它必須介於公式計算的MIN和MAX值之間
MIN [Settle count * T(Timer clock)] > T(HS_SETTLE)_MIN
MAX [Settle count * T(Timer clock)] < T(HS-PREPARE)+T(HS_ZERO) - 4*T(Timer clock)
settle_cnt(即穩定計數)– 必須根據感測器輸出特性配置該值,以確保感測器的 PHY
發送器與 MSM 的 PHY 接收器無障礙同步。
對於 28 nm 以及更小的 MSM 晶元,使用以下公式計算穩定計數:
settle_cnt = T(HS_SETTLE)_avg /T(TIMER_CLK),
其中 T(HS_SETTLE)_avg = (T(HS_SETTLE)_min + T(HS_SETTLE)_max) / 2,如傳
感器數據表所指示
如果sensor可以直接流式傳輸HDR幀,該函數才有用。
這里的 rolloff compensations = Lens Shading Correction (LSC)
有些sensor可以自己內部做lsc補償。rolloff_config就是用了配置sensor的這些信息。
注意:如果你使用了sensor LSC補償,平台端 lsc補償就要關閉,否則雙倍補償,可能會造成圖片失真。
typedef enum {
SENSOR_DELAY_EXPOSURE, /* delay for exposure /
SENSOR_DELAY_ANALOG_SENSOR_GAIN, / delay for sensor analog gain /
SENSOR_DELAY_DIGITAL_SENSOR_GAIN, / delay for sensor digital gain /
SENSOR_DELAY_ISP_GAIN, / delay for sensor ISP (error) gain*/
SENSOR_DELAY_MAX,
} sensor_delay_type_t;
SENSOR_DELAY_EXPOSURE – Sets the exposure of frame N at frame N + delay
SENSOR_DELAY_ANALOG_SENSOR_GAIN – Sets the analog gain register at frame N + delay
SENSOR_DELAY_DIGITAL_SENSOR_GAIN – Sets the digital gain register at frame N + delay
SENSOR_DELAY_ISP_GAIN – Passes the isp digital gain to the isp mole at frame N + delay
如果出現ae閃爍問題,可以嘗試修改延遲,讓gain和expose同步。
This is the readout time (in nanoseconds) of the sensor』s analog-to-digital converter. Usually it is
the minimum line time when the sensor is running at the maximum pixel clock.
NOTE: This is the sensor mole』s own information. Refer to the sensor vendor for more information
noise_coeff 小波里用來定義雜訊的模板
雜訊系數模型: N(x) = sqrt(Sx + O)
這些參數一般由tunning團隊修改。
關於角度
注意:
如果 <MountAngle>360</MountAngle>; 這個值配置成360度,那麼以dtsi配置的角度為准。
源碼:
關於幀率
https://www.cnblogs.com/ZHJEE/p/10351155.html
繼續當一名咸魚( ̄︶ ̄)!
B. android鎵嬫満閮芥湁鍝浜泂ensor
1.Sensor Type
閲嶅姏鎰熷簲/鍔犻熷害浼犳劅鍣 (G-Sensor)
鍏夋劅搴 (Light-Sensor)
娓╁害鎰熷簲
鏂瑰悜鎰熷簲
紓佸満銆
涓磋繎鎬
2.濡備綍瀹炵幇Sensor緙栫▼
a.鑾峰彇緋葷粺鏈嶅姟錛圫ENSOR_SERVICE)榪斿洖涓涓猄ensorManager 瀵硅薄
sensormanager = (SensorManager)getSystemSeriver(SENSOR_SERVICE);
b.閫氳繃SensorManager瀵硅薄鑾峰彇鐩稿簲鐨凷ensor綾誨瀷鐨勫硅薄
sensorObject = sensormanager.getDefaultSensor(sensor Type);
c.澹版槑涓涓猄ensorEventListener 瀵硅薄鐢ㄤ簬渚﹀惉Sensor 浜嬩歡錛屽苟閲嶈澆onSensorChanged鏂規硶
SensorEventListener sensorListener = new SensorEventListener(){
};
d.娉ㄥ唽鐩稿簲鐨凷ensorService
sensormanager.registerListener(sensorListener, sensorObject, Sensor TYPE);
e.閿姣佺浉搴旂殑SensorService
sensormanager.unregisterListener(sensorListener, sensorObject);
f: SensorListener 鎺ュ彛鏄浼犳劅鍣ㄥ簲鐢ㄧ▼搴忕殑涓蹇冦傚畠鍖呮嫭涓や釜蹇呴渶鏂規硶錛
銆銆 onSensorChanged(int sensor,float values[]) 鏂規硶鍦ㄤ紶鎰熷櫒鍊兼洿鏀規椂璋冪敤銆
璇ユ柟娉曞彧瀵瑰彈姝ゅ簲鐢ㄧ▼搴忕洃瑙嗙殑浼犳劅鍣ㄨ皟鐢(鏇村氬唴瀹硅佷笅鏂)銆傝ユ柟娉曠殑鍙傛暟鍖呮嫭錛氫竴涓鏁存暟錛屾寚紺烘洿鏀圭殑浼犳劅鍣;涓涓嫻鐐瑰兼暟緇勶紝琛ㄧず浼犳劅鍣ㄦ暟鎹鏈韜銆傛湁浜涗紶鎰熷櫒鍙鎻愪緵涓涓鏁版嵁鍊礆紝鍙︿竴浜涘垯鎻愪緵涓変釜嫻鐐瑰箋傛柟鍚戝拰鍔犻熻〃浼犳劅鍣ㄩ兘鎻愪緵涓変釜鏁版嵁鍊箋
銆銆 褰撲紶鎰熷櫒鐨勫噯紜鎬ф洿鏀規椂錛屽皢璋冪敤 onAccuracyChanged(int sensor,int accuracy) 鏂規硶銆傚弬鏁板寘鎷涓や釜鏁存暟錛氫竴涓琛ㄧず浼犳劅鍣錛屽彟涓涓琛ㄧず璇ヤ紶鎰熷櫒鏂扮殑鍑嗙『鍊箋
3.鍏充簬G-Sensor
Android 鍔犻熷害浼犳劅鍣ㄧ殑綾誨瀷鏄 Sensor.TYPE_ACCELEROMETER
閫氳繃 android.hardware.SensorEvent 榪斿洖鍔犻熷害浼犳劅鍣ㄥ箋
鍔犻熷害浼犳劅鍣ㄨ繑鍥炲肩殑鍗曚綅鏄鍔犻熷害鐨勫崟浣 m/s^2(綾蟲瘡浜屾℃柟縐)錛屾湁涓変釜鏂瑰悜鐨勫煎垎鍒鏄
銆銆values[0]: x-axis 鏂瑰悜鍔犻熷害
銆銆values[1]: y-axis 鏂瑰悜鍔犻熷害
銆銆values[2]: z-axis 鏂瑰悜鍔犻熷害
銆銆鍏朵腑x,y,z鏂瑰悜鐨勫畾涔夋槸浠ユ按騫蟲斁緗鍦ㄧ殑鎵嬫満鐨勫彸涓嬭剼涓哄弬鐓х郴鍧愭爣鍘熺偣
銆銆x 鏂瑰悜灝辨槸鎵嬫満鐨勬按騫蟲柟鍚戱紝鍙充負姝
銆銆y 鏂瑰悜灝辨槸鎵嬫満鐨勬按騫沖瀭鐩存柟鍚戱紝鍓嶄負姝
銆銆y 鏂瑰悜灝辨槸鎵嬫満鐨勭┖闂村瀭鐩存柟鍚戱紝澶╃┖鐨勬柟鍚戜負姝o紝鍦扮悆鐨勬柟鍚戜負璐
闇瑕佹敞鎰忕殑鏄錛岀敱浜庡湴鐞冨滻鏈夌殑閲嶅姏鍔犻熷害g (鍊間負9.8 m/s^2)錛
銆銆鍥犳ょ幇瀹炰腑瀹為檯鍔犻熷害鍊煎簲璇ユ槸 z鏂瑰悜榪斿洖鍊 - 9.8 m/s^2.
銆銆姣斿備綘浠 2 m/s^2 鐨勫姞閫熷害灝嗘墜鏈烘姏璧鳳紝榪欐椂z鏂瑰悜鐨勮繑鍥炲煎簲璇ユ槸 11.8 m/s^2.
銆銆鍙嶄箣鑻ヤ互鎵嬫満浠2 m/s^2 鐨勫姞閫熷害鍧犺惤錛屽垯z鏂瑰悜鐨勮繑鍥炲煎簲璇ユ槸 7.8 m/s^2.
銆銆x,y鏂瑰悜鍒欐病鏈変笂榪伴檺鍒躲
C. android如何實現陀螺儀 sensor 在 android 嗎
千鋒扣丁學堂Android開發為您解答:
sensors.h中還定義了其他各種sensor。要實現的就是這兩個:
#define SENSOR_TYPE_MAGNETIC_FIELD 2
#define SENSOR_TYPE_ORIENTATION 3
在/hardware/sensors/sensors.cpp 中添加對MAGNETIC_FIELD和ORIENTATION 的支持
[cpp] view plain
//加入需要的宏定義
#define ID_BASE SENSORS_HANDLE_BASE
#define ID_ACCELERATION (ID_BASE+0)
#define ID_MAGNETIC_FIELD (ID_BASE+1)
#define ID_ORIENTATION (ID_BASE+2)
#define S_HANDLE_ACCELEROMETER (1<<ID_ACCELERATION)
#define S_HANDLE_MAGNETIC_FIELD (1<<ID_MAGNETIC_FIELD)
#define S_HANDLE_ORIENTATION (1<<ID_ORIENTATION)
#define SENSORS_NUM 4
#define SUPPORTED_SENSORS ((1<<NUM_SENSORS)-1)
//在 sensor_t sensors_list[] 中添加兩個sensor的信息,
//這些只是一些Sensor的信息,應用程序可以獲取到。
#ifdef MAGNETIC_FIELD
{
name : "XXX 3-axis Magnetic field sensor",
vendor : "XXX company",
version : 1,
handle : S_HANDLE_MAGNETIC_FIELD,
type : SENSOR_TYPE_MAGNETIC_FIELD,
maxRange : 600.0f,//最大范圍
resolution : 30.0f,//最小解析度
power : 6.7f,//這個不太懂
},
#endif
#ifdef ORIENTATION
{
name: "XXX Orientation sensor",
vendor: "XXX company",
version: 1,
handle: S_HANDLE_ORIENTATION,
type: SENSOR_TYPE_ORIENTATION,
maxRange: 360,
resolution: 0.1,
power: 20,
},
#endif
//定義一個結構來保存orientation的信息
static struct orientation{
float azimuth;
float pitch;
float roll;
}orientation;
//在 control__open_data_source()函數中打開設備
static native_handle_t*
control__open_data_source(struct sensors_control_device_t *dev)
{
SensorControl* ctl = (void*)dev;
native_handle_t* handle;
int fd_m = open (MAGNETIC_DATA_DEVICE, O_RDONLY);
LOGD ("Open Magnetic Data source: %d, %d/n", fd_m, errno);
if (fd_m>= 0)
{
dev->fd[ID_MAGNETIC_FIELD] = p(fd_m);
}
return handle;
}
//實現數據的打開和關閉函數
static int
data__data_open(struct sensors_data_device_t *dev, native_handle_t* handle)
{
struct sensors_data_context_t *dev;
dev = (struct sensors_data_context_t *)device;
for(int i=0 ;i<SENSORS_NUM; i++)
{
dev->fd[i] = p(handle->data[i]);
}
native_handle_close(handle);
native_handle_delete(handle);
return 0;
}
static int
data__data_close(struct sensors_data_device_t *dev)
{
struct sensors_data_context_t *dev;
dev = (struct sensors_data_context_t *)device;
for(int i=0 ;i<SENSORS_NUM; i++)
{
if (dev->fd[i] >= 0)
{
close(dev->fd[i]);
}
dev->fd[i] = -1;
}
return 0;
}
//最關鍵的poll函數
static int
data__poll(struct sensors_data_device_t *dev, sensors_data_t* values)
{
SensorData* data = (void*)dev;
int fd = data->events_fd;
//判斷設備是否打開
if(dev->fd[ID_MAGNETIC_FIELD] < 0)
{
LOGD("In %s dev[%d] is not open!/n",__FUNCTION__ ,ID_MAGNETIC_FIELD);
return -1;
}
pollfd pfd[SENSORS_NUM] =
{
//省略其他sensor代碼
{
fd: dev->fd[ID_MAGNETIC_FIELD],
events: POLLIN,
revents: 0
},
//省略其他sensor代碼
};
int err = poll (pfd, SENSORS_NUM, s_timeout);
unsigned int mask = SUPPORTED_SENSORS;
static unsigned int poll_flag=0;
if(poll_flag==0)
{
poll_flag = mask;
}
//省略其他sensor
if(poll_flag&(1<<ID_MAGNETIC_FIELD))
{
if((pfd[ID_MAGNETIC_FIELD].revents&POLLIN) == POLLIN)
{
char rawData[6];
err = read (dev->fd[ID_MAGNETIC_FIELD], &rawData, sizeof(rawData));
if(err<0)
{
LOGE("read magnetic field ret:%d errno:%d/n", err, errno);
return err;
}
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
data->time = timespec_to_ns(&t);
data->sensor = SENSOR_TYPE_MAGNETIC_FIELD;
data->magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
//上報的數據單位要轉換成 uTesla
data->magnetic.x = ( (rawData[1] << 8 ) | rawData[0])/ MAGNETIC_CONVERT;
data->magnetic.y = ( (rawData[3] << 8 ) | rawData[2])/ MAGNETIC_CONVERT;
data->magnetic.z = ( (rawData[5] << 8 ) | rawData[4])/ MAGNETIC_CONVERT;
//把陀螺儀需要的數據計算出來,用atan2(),頭文件要加上#include <math.h>
float azimuth = atan2( (float)(data->magnetic.x ),(float)(data->magnetic.y) );
if(azimuth<0)
{
azimuth = 360 - fabs(azimuth*180/PI);
}
else
{
azimuth = azimuth*180/PI;
}
orientation.azimuth = 360-azimuth;
//rotation around the X axis.+180~-180 degree
orientation.pitch = atan2( (float)(data->magnetic.y ),(float)(data->magnetic.z)
)*180/PI;
//rotation around the Y axis +90~-90 degree
float roll = atan2( (float)(data->magnetic.x ),(float)(data->magnetic.z) )
*180/PI;
if (roll > 90)
{
roll = -(180.0-roll);
}
else if (roll < -90)
{
roll = 180 + roll;
}
orientation.roll = roll;
}
return S_HANDLE_MAGNETIC_FIELD;
}
if(poll_flag&(1<<ID_MAGNETIC_FIELD))
{
//數據已經計算好了直接上報就行
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
data->time = timespec_to_ns(&t);
data->sensor = SENSOR_TYPE_ORIENTATION;
data->orientation.azimuth = orientation.azimuth;
data->orientation.pitch = orientation.pitch;
data->orientation.roll = orientation.roll;
poll_flag &= ~(1<<ID_ORIENTATION);
return S_HANDLE_ORIENTATION;
}
}
D. android如何實現陀螺儀 sensor 在 android 嗎
設備中的三自由度Orientation
Sensor就是一個可以識別設備相對於地面,繞x、y、z軸轉動角度的感應器(自己的理解,不夠嚴謹)。智能手機,平板電腦有了它,可以實現很多好玩的應用,比如說指南針等。
我們可以用一個磁場感應器(magnetic sensor)來實現。
磁場感應器是用來測量磁場感應強度的。一個3軸的磁sensor
IC可以得到當前環境下X、Y和Z方向上的磁場感應強度,對於Android中間層來說就是讀取該感應器測量到的這3個值。當需要時,上報給上層應用程序。磁感應強度的單位是T(特斯拉)或者是Gs(高斯),1T等於10000Gs。
先來看看android定義的坐標系,在/hardware/libhardware/include/hardware/sensors.h中有個圖。
求z和x的反正切可得到此值。
sensors.h中還定義了其他各種sensor。要實現的就是這兩個:
#define SENSOR_TYPE_MAGNETIC_FIELD 2
#define SENSOR_TYPE_ORIENTATION 3
在/hardware/sensors/sensors.cpp 中添加對MAGNETIC_FIELD和ORIENTATION 的支持
E. android 非上層程序怎麼調用sensor
Android上層應用apk到G-sensor driver的大致流程: Android HAL層,即硬體抽象層,是Google響應廠家「希望不公開源碼」的要求推出的新概念 1,源代碼和目標位置 源代碼: /hardware/libhardware目錄,該目錄的目錄結構如下: /hardware/libhardware/hardware.c編譯成libhardware.so,目標位置為/system/lib目錄 /hardware/libhardware/include/hardware目錄下包含如下頭文件: hardware.h 通用硬體模塊頭文件 bit.h bit模塊頭文件 gralloc.h gralloc模塊頭文件 qemud.h qemud模塊頭文件 sensors.h 感測器模塊頭文件 /hardware/libhardware/moles目錄下定義了很多硬體模塊 這些硬體模塊都編譯成xxx.xxx.so,目標位置為/system/lib/hw目錄 2,Android對於Sensor的API定義在 hardware/libhardware/include/hardware/sensor.h中,要求在sensor.so提供以下8個API函數 [控制方面] int (*open_data_source)(struct sensors_control_device_t *dev); int (*activate)(struct sensors_control_device_t *dev, int handle, int enabled); int (*set_delay)(struct sensors_control_device_t *dev, int32_t ms); int (*wake)(struct sensors_control_device_t *dev); [數據方面] int (*data_open)(struct sensors_data_device_t *dev, int fd); int (*data_close)(struct sensors_data_device_t *dev); int (*poll)(struct sensors_data_device_t *dev, sensors_data_t* data); [模塊方面] int (*get_sensors_list)(struct sensors_mole_t* mole, struct sensor_t const** list); 在java層Sensor的狀態控制由SensorService來負責,它的java代碼和JNI代碼分別位於: frameworks/base/services/java/com/Android/server/SensorService.java frameworks/base/services/jni/com_Android_server_SensorService.cpp 在Java層Sensor的數據控制由SensorManager來負責,它的java代碼和JNI代碼分別位於: frameworks/base/core/java/Android/hardware/SensorManager.java frameworks/base/core/jni/Android_hardware_SensorManager.cpp Android framework中與sensor通信的是sensorService.java和sensorManager.java。 sensorService.java的具體通信是通過JNI調用sensorService.cpp中的方法實現的。 sensorManager.java的具體通信是通過JNI調用sensorManager.cpp中的方法實現的。 sensorService.cpp和sensorManger.cpp通過hardware.c與sensor.so通信。其中sensorService.cpp實現對sensor的狀態控制,sensorManger.cpp實現對sensor的數據控制。 sensor.so通過ioctl控制sensor driver的狀態,通過打開sensor driver對應的設備文件讀取G-sensor採集的數據。 Android SDK提供了4個類來於sensor通信,分別為 sensor,sensorEvent,sensorEventListener,sensorManager。其中 sensorEventListener用來在sensorManager中注冊需要監聽的sensor類型。 sensorManager.java提供registrater(),unregistrater()介面供sensorEventListener使用。 sensorManager.java不斷輪詢從sensor.so中取數據。取到數據後送給負責監聽此類型sensor的 sensorEventListener.java。sensorEventListener.java通過在sensorManager.java中注冊可以監聽特定類型的sensor傳來的數據。 系統啟動時執行systemProcess,會啟動sensorService.java,在sensorService.java的構造函數中調用JNI方法_sensor_control_init()。 sensorService.cpp中相應的方法Android_int()會被執行。該函數會調用hardware.c中的方法hw_get_mole()此函數又通過調用load()函數在system/lib/hw下查找sensor.so 查找時會根據harware.c中定義好的sensor.*.so的擴展名的順序查找,找到第一個匹配的時候即停止,並將該sensor.so中定義好的一個全局變數HAL_MODULE_INFO_SYM帶回。該變數包含的一個 重要信息是它的一個成員結構變數中包含的一個函數指針open,該指針所指函數會對一個device結構變數賦值,從而帶出sensorService.cpp和sensorManager.cpp與sensor通信所需要的全部信息。 device結構變數有兩種變體分別供sensorService.cpp和sensorManaer.cpp使用。其中主要是一些函數指針指向與sensor通信的函數。 sensorService.cpp和sensorManager.cpp在得到HAL_MODULE_INFO_SYM結構後都會調用 sensors.h的inline函數open()通過HAL_MODULE_INFO_SYM的open函數指針將所需的device信息取回。 系統在啟動activityManager.java時,它會啟動sensorManager.java,它也會調用hardware.c中的方法hw_get_mole()帶回HAL_MODULE_INFO_SYM。
F. android gsensor 休眠震動喚醒功能如何實現
一、喚醒源
設備休眠後,通過觸發喚醒源使設備恢復正常工作模式。設備喚醒源有多種,對於Android設備常見的就有PowerKey、來電喚醒、Alarm喚醒等。
喚醒源的實現處於內核空間,本文重點討論下PowerKey作為喚醒源的具體實現。
二、PowerKey喚醒源
PowerKey喚醒設備的原理,本質其實就是中斷。
PowerKey連接到CPU的一個輸入(Input)引腳(Pin)上,該Pin運行在中斷模式上。一旦PowerKey按下,引發Pin中斷;而該中斷具有喚醒CPU的功能,於是設備得以喚醒。
三、PowerKey對應的Pin
Configuration
和PowerKey相連的Pin的具體配置位於板級dts文件中,比如如下配置:
arch/arm/boot/dts/xxxxx.dts
power-key {
/** 是CPU的哪個Pin */
gpios = <&gpio0 GPIO_A5 GPIO_ACTIVE_LOW>;
/** Key code */
linux,code = <116>;
/** 起個名字 */
label = "power";
/** 該Pin具有wakeup的功能 */
gpio-key,wakeup;
};
著重說下linux,code =
<116>,116怎麼來的?
對於鍵盤,每一個按鍵都有唯一的編碼,在Linux中,編碼值位於:
input.h (kernelincludeuapilinux)
/*
* Keys and buttons
*/
#define KEY_RESERVED 0
#define KEY_ESC 1
#define KEY_BACKSPACE 14
#define KEY_TAB 15
#define KEY_POWER 116 /* SC System Power Down */
可知,PowerKey的編碼也在該文件中,且編碼值為116;一旦按下PowerKey,該值作為鍵值傳到input_event結構體的code成員變數中:
input.h (kernelincludeuapilinux)
/*
* The event structure itself
*/
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
之後我們會寫個Linux應用程序讀取code值。