高通Android平台 驱动层软件学习总结
一、在高通平台8X25中有两个 .defconfig,分别是msm7627a_defconfig和msm7627a-perf_defconfig。编译的时候会把2个文件的内容合并在一起成为最终的outtargetproductmsm8625objKERNEL_OBJ.defconfig文件,合并规则是:
1、系统会设定一个默认的参考defconfig文件,在deviceqcomMsm7627a AndroidBoard.mk 中设定:
#----------------------------------------------------------------------
# Compile Linux Kernel
#----------------------------------------------------------------------
ifeq ($(KERNEL_DEFCONFIG),)
KERNEL_DEFCONFIG := msm7627a-perf_defconfig
Endif
2、对比默认参考文件,复制默认参考文件中没有的内容到.defconfig;
3、若两个文件中都有相同的内容选项,并且设置相同(Y/N),则只复制一次内容到.defconfig。
4、若两个文件中都有相同的内容选项,但是设置不同(Y/N),则依据默认参考文件的内容复制到.defconfig。
二、各设备的板级文件在kernelarcharmmach-msm中。比如触摸屏的在board-msm7627a-io.c文件中定义。传感器的在board-msm7627a-sensor.c中。
三、编译kernel的MK规则在kernelAndroidKernel.mk文件中。包括生成的.defconfig,zImage,system,modules。
四、高通I2C(控制器-adapter)驱动使用的是platform方式注册,然后在probe中使用i2c_add_numbered_adapter (&dev->adap_pri) 注册到I2C_BUS上。
1、在kernelarcharmMach-msm Board-msm7x27a.c中有adapter的板级信息:
static struct msm_i2c_platform_data msm_gsbi0_qup_i2c_pdata = {
.clk_freq = 100000,
.msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
};
I2C硬件接口配置static struct msm_gpio qup_i2c_gpios_hw[] = {
{ GPIO_CFG(60, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
"qup_scl" },
{ GPIO_CFG(61, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
"qup_sda" },
{ GPIO_CFG(131, 2, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
"qup_scl" },
{ GPIO_CFG(132, 2, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
"qup_sda" },
};
2、在kerneldriversi2cBussesI2c-msm.c 中有adapter的驱动实现。
五、板级文件中的i2c_board_info (即表示一个i2c从设备,其中包含了设备的一些信息和资源,如设备名、设备地址)注册到系统后会在两个地方使用。
第一处是在i2c_add_adapter或者i2c_add_numbered_adapter()中与i2c_adapter共同生成i2c_client;
第二处是在i2c_add_driver()中用来匹配i2c_driver中的idtable。因此在写i2c_driver时应该包括一个i2c_device_id,这个id中的内容必须与i2c_board_info中的内容相同才能匹配。
因此在一个系统中有几个i2c设备就会有多少个i2c_client和i2c_driver(也有一个i2c_driver支持多个i2c设备的情况,只需将要支持的设备名加入idtable中和相应的i2c_board_info)。
六、dev_info(&client->dev,"Update Step 2:Entering upgrade mode.n");
此函数用来在内核启动时打印参数,和printk 功能差不多。
七、android LED设备从上到下分析
1、framwork 层: frameworksbaseservicesjavacomandroidServer LightsService.java 提供java调用jni层方法。一般作为service启动。
2、jni 层: frameworksbaseservicesJn com_android_server_LightsService.cpp
3、hardware层: hardwareqcomdisplayLiblight Lights.c
4、驱动层: kerneldriversLeds Leds-pmic-mpp.c
八 TP
set_bit(EV_ABS, idev->evbit);
set_bit(ABS_X, idev->absbit);
set_bit(ABS_Y, idev->absbit);
set_bit(ABS_Z, idev->absbit);
前四行说的是设备支持坐标事件,包括X坐标,Y坐标事件,Z坐标事件。
input_set_abs_params(idev, ABS_X, -64, 64, 4, 0);
对于X轴范围是-64到+64,数据误差是-4到+4,中心平滑位置是0
input_set_abs_params(idev, ABS_Y, -64, 64, 4, 0);
input_set_abs_params(idev, ABS_Z, -64, 64, 4, 0);
对于Y和Z轴,和X轴一样
input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
pdata->x_max, 0, 0);这里的pdata->x_max是指屏幕x方向的分辨率,是在板级支持包中的platform_data中定义的,这样做是为了使TP的报点范围和LCD的分辨率一致。
九 android输入系统之TP报按键和报坐标时对下面功能键的处理
1、 ap-srcframeworksbasecorejavaandroidView KeyEvent.java :定义了android输入系统框架层的各种事件、键值等。
2、 ap-srcframeworksbasecorejavaandroidView WindowManagerPolicy.java :定义了android输入系统对输入事件、按键等的处理策略标志等。比如FLAG_VIRTUAL :处理虚拟按键的策略标志。
3、 ap-srcframeworksbasecorejavaandroidView HapticFeedbackConstants.java :定义了android输入系统对输入事件,如按键的反馈标志,比如,按下按键时,就会置位KEYBOARD_TAP ,而按下虚拟按键则是置位VIRTUAL_KEY。这样在检测到这些反馈标志后就会调用指定的反馈函数,如按下HOME键,调用点亮按键灯和马达震动函数。
4、 ap-srcframeworksbasepolicysrccomandroidinternalpolicyImpl PhoneWindowManager.java :android主窗口,主界面控制总调用程序,这个就是我们在开机后看到的主界面了,在这里面会调用其它的一些服务。比如打电话,按下HOME键时,回到主界面,调用按键灯服务和马达服务等。
5、应用实例 :在调试海尔HC54XX系列触摸屏的时候,由于下面4个功能键是使用特殊方法实现,即在该区域不会报坐标,但是按下相应的按键时会报一个特殊值,这样在根据这个特殊值再转换为报按键事件,虽然实现了特殊功能键的功能,但是在按键的时候,马达和按键灯都不起作用。这是因为android在PhoneWindowManager.java中只对虚拟按键做了马达和按键灯的反馈处理,但是直接报按键的没有这样处理,因此要实现直接报按键也要有这个功能就必须在PhoneWindowManager.java这里面添加对应的处理。我的方法是在PhoneWindowManager.java中的public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) 函数中添加对直接报按键的处理:
interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn){
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final int keyCode = event.getKeyCode();
//add by Andy.jiang to use MENU HOME BACK SEARCH key event to open the led and vibrator start
if((keyCode==KeyEvent.KEYCODE_MENU)||(keyCode== KeyEvent.KEYCODE_HOME)||
(keyCode==KeyEvent.KEYCODE_BACK)||(keyCode== KeyEvent.KEYCODE_SEARCH)){
policyFlags |= WindowManagerPolicy.FLAG_MENU;//标志下面4个功能键按下
}
if (down && (policyFlags & WindowManagerPolicy.FLAG_MENU) != 0){
try {
mLight.turnOnButtonLightOneShot();//点亮按键灯
Slog.e("hc54xx", "function key for turn on button light ok.");
} catch(RemoteException e) {
Slog.e(TAG, "function key for turn on button light failed.");
}
performHapticFeedbackLw(null, HapticFeedbackConstants.KEYBOARD_TAP, false);//调用马达震动
}
//add by Andy.jiang to use MENU HOME BACK SEARCH key event to open the led and vibrator end
其中函数performHapticFeedbackLw()原型是:
public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
if (effectId == HapticFeedbackConstants.VIRTUAL_KEY) {
// Click home menu search back button, in this time effectId == VIRTUAL_KEY, LED should be lighted.
// Seprate LED control from haptic control.
// when effectId == HapticFeedbackConstants.VIRTUAL_KEY, should turnOnButtonLightOneShot.
// turnOnButtonLightOneShot() will contorl LED brightness and diaplay time.
try {
mLight.turnOnButtonLightOneShot();
} catch(RemoteException e) {
Slog.e(TAG, "remote call for turn on button light failed.");
}
}
final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
return false;
}
long[] pattern = null;
switch (effectId) {
case HapticFeedbackConstants.LONG_PRESS:
pattern = mLongPressVibePattern;
break;
case HapticFeedbackConstants.VIRTUAL_KEY:
pattern = mVirtualKeyVibePattern;
break;
case HapticFeedbackConstants.KEYBOARD_TAP:
pattern = mKeyboardTapVibePattern;
break;
case HapticFeedbackConstants.SAFE_MODE_DISABLED:
pattern = mSafeModeDisabledVibePattern;
break;
case HapticFeedbackConstants.SAFE_MODE_ENABLED:
pattern = mSafeModeEnabledVibePattern;
break;
default:
return false;
}
if (pattern.length == 1) {
// One-shot vibration
mVibrator.vibrate(pattern[0]);
Slog.e("hc54xx", "function key for turn on vibrator.");//add by Andy
} else {
// Pattern vibration
mVibrator.vibrate(pattern, -1);
Slog.e("hc54xx", "function key for turn off vibrator.");//add by Andy
}
return true;
}