bugfix:reboot模式下不能开机

system:android4.2

platform:rk3026

pum: axp192

系统在插充电器的时候关机进入充电模式,当显示电池图标的时候不能开机,黑屏的时候能开机。

henglong@henglong-desktop:~/projects/ricks/rk3026/kernel$ git show 58af187f647e66cfcc5a86508bf2ee0ed69a1fa3
commit 58af187f647e66cfcc5a86508bf2ee0ed69a1fa3
Author: henglong <henglong@henglong-host.(none)>
Date:   Wed Mar 26 08:36:26 2014 +0800


    ricks: fix cannot poweron by long press power key issue when machine is in boot status


diff --git a/kernel/drivers/power/axp_power/axp-sply.c b/kernel/drivers/power/axp_power/axp-sply.c
index 17cf0cc..ee4b8d4 100755
--- a/kernel/drivers/power/axp_power/axp-sply.c
+++ b/kernel/drivers/power/axp_power/axp-sply.c
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */


+#include <linux/console.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -355,6 +356,14 @@ static void axp_change(struct axp_charger *charger)
 static void axp_presslong(struct axp_charger *charger)
 {
        DBG("press long\n");
+//if(strstr(cmdline,“charger”))//在充电
+if(strstr(saved_command_line,"charger"))
+{
+       printk("charge icon for reboot\n");
+       // arm_pm_restart(0, "reboot");
+       arm_pm_restart(0, NULL);
+}else
+{
 #if defined (CONFIG_AXP_PEKINFO)
        input_report_key(powerkeydev, KEY_POWER, 1);
        input_sync(powerkeydev);
@@ -364,6 +373,7 @@ static void axp_presslong(struct axp_charger *charger)
        input_sync(powerkeydev);
 #endif
 }
+}


 static void axp_pressshort(struct axp_charger *charger)

打了以上的补丁之后可以了。 就是在axp长按power键的时候判断是不是在充电,如果在充电状态就重启。

有一个函数很有意思------strstr(saved_command_line,"charger"); 以前很少用到,此函数用法如下:

STRSTR(3)                                             Linux Programmer's Manual                                            STRSTR(3)

NAME
       strstr, strcasestr - locate a substring

SYNOPSIS
       #include <string.h>

       char *strstr(const char *haystack, const char *needle);

       #define _GNU_SOURCE

       #include <string.h>

       char *strcasestr(const char *haystack, const char *needle);

DESCRIPTION
       The  strstr() function finds the first occurrence of the substring needle in the string haystack.  The terminating '\0' char‐
       acters are not compared.

       The strcasestr() function is like strstr(), but ignores the case of both arguments.

RETURN VALUE
       These functions return a pointer to the beginning of the substring, or NULL if the substring is not found.

CONFORMING TO
       The strstr() function conforms to C89 and C99.  The strcasestr() function is a non-standard extension.

BUGS
       Early versions of Linux libc (like 4.5.26) would not allow an empty needle  argument  for  strstr().   Later  versions  (like
       4.6.27) work correctly, and return haystack when needle is empty.

SEE ALSO
       index(3),  memchr(3),  rindex(3),  strcasecmp(3),  strchr(3),  strpbrk(3),  strsep(3),  strspn(3), strtok(3), wcsstr(3), fea‐
       ture_test_macros(7)

COLOPHON
       This page is part of release 3.23 of the Linux man-pages project.  A  description  of  the  project,  and  information  about
       reporting bugs, can be found at http://www.kernel.org/doc/man-pages/.

GNU   

中文版


头文件:#include <string.h>

定义函数:char *strstr(const char *haystack, const char * needle);

函数说明:strstr()会从字符串haystack 中搜寻字符串needle,并将第一次出现的地址返回。

返回值:返回指定字符串第一次出现的地址,否则返回0。

范例
#include <string.h>
main(){
    char * s = "012345678901234567890123456789";
    char *p;
    p = strstr(s, "901");
    printf("%s\n", p);
}

执行结果:
9.01E+21


ok,那么 saved_command_line又是什么东东?记得有个同事(以下都用春春代替)说过,rk的bootmode充电图标显示是用cmdline的方式通知上层,然后由上层来显示电池充电图标。看来这个command_line是和那个玩意是一致的。研究一下先--cmdline是what?

saved_command_line是一个全局变量,在kernel/init/main.c文件中定义如下:

/* Untouched saved command line (eg. for /proc) */
char *saved_command_line;

在kernel/drivers/power/rk29_charger_display.c文件中:

#ifdef CONFIG_POWER_ON_CHARGER_DISPLAY
//int charger_mode=0;	     	//1:charge,0:not charge
static void add_bootmode_charger_to_cmdline(void)
{
	char *pmode=" androidboot.mode=charger";
	//int off = strlen(saved_command_line);
	char *new_command_line = kzalloc(strlen(saved_command_line) + strlen(pmode) + 1, GFP_KERNEL);
	sprintf(new_command_line, "%s%s", saved_command_line, pmode);
	saved_command_line = new_command_line;
	//strcpy(saved_command_line+off,pmode);

	//int off = strlen(boot_command_line);
	//strcpy(boot_command_line+off,pmode);

	printk("Kernel command line: %s\n", saved_command_line);
}


找到了cmdline.c文件,kernel/fs/proc/cmdline.c文件内容如下:

  1 #include <linux/fs.h>
  2 #include <linux/init.h>
  3 #include <linux/proc_fs.h>
  4 #include <linux/seq_file.h>
  5
  6 static int cmdline_proc_show(struct seq_file *m, void *v)
  7 {
  8     seq_printf(m, "%s\n", saved_command_line);
  9     return 0;
 10 }
 11
 12 static int cmdline_proc_open(struct inode *inode, struct file *file)
 13 {
 14     return single_open(file, cmdline_proc_show, NULL);
 15 }
 16
 17 static const struct file_operations cmdline_proc_fops = {
 18     .open       = cmdline_proc_open,
 19     .read       = seq_read,
 20     .llseek     = seq_lseek,
 21     .release    = single_release,
 22 };
 23
 24 static int __init proc_cmdline_init(void)
 25 {
 26     proc_create("cmdline", 0, NULL, &cmdline_proc_fops);
 27     return 0;
 28 }
 29 module_init(proc_cmdline_init);
~
~

到这里基本清楚了,saved_command_line是一个全局变量,任何人想向android发送命令都可以把命令写到这个字符串里面去,然后通过proc_create虚拟文件和android上层交互。

proc_create()函数另外开一篇文章介绍。


使用 /proc 文件系统来访问 Linux 内核的内容

这个虚拟文件系统在内核空间和用户空间之间打开了一个通信窗口

/proc 文件系统是一个虚拟文件系统,通过它可以使用一种新的方法在 Linux® 内核空间和用户空间之间进行通信。在 /proc 文件系统中,我们可以将对虚拟文件的读写作为与内核中实体进行通信的一种手段,但是与普通文件不同的是,这些虚拟文件的内容都是动态创建的。本文对 /proc 虚拟文件系统进行了介绍,并展示了它的用法。



你可能感兴趣的:(linux,proc,cmdline)