I.MX6 shutdown by software
/************************************************************************ * I.MX6 shutdown by software * 声明: * 有时候我们的系统可能并没有像手机那样的开关机键,所以我么这个时候 * 需要提供软件关机功能,本文直接通过JNI操作设备节点进行控制,并没有采用 * STUB来控制,当然目前对这块的操作也不熟练。 * * 2015-12-20 深圳 南山平山村 曾剑锋 ***********************************************************************/ \\\\\\\\\\\\\\-*- 目录 -*-/////////////// | 一、参考文档: | 二、修改按键驱动程序: | 三、板级文件注册按键设备: | 四、添加shutdown设备节点,便于控制: | 五、关闭关机时的提示框: | 六、关闭watchdog: | 七、使用JNI进行测试: | 八、JNI对应的Java文件: ---------------------------------------- 一、参考文档: Android开发 调用系统隐藏API http://www.pocketdigi.com/20130519/1058.html 定做Android关机界面 http://233.io/article/1019041.html Android下实现自动关机的方法总结 http://233.io/article/1019041.html 二、修改按键驱动程序: cat drivers/input/keyboard/gpio_keys.c ...... //主要是为了能够指向input的设备,我们能够在自己函数里实现单独控制 struct input_dev *this_input; ...... /* 添加这个我们自己的函数,并声明为系统全局符号 */ void this_input_report_event(int mode) { unsigned int type = EV_KEY; switch (mode) { case 1 : // for power off input_event(this_input, type, KEY_POWER, 1); input_sync(this_input); msleep(2000); input_event(this_input, type, KEY_POWER, 0); input_sync(this_input); break; case 2 : // for stand by input_event(this_input, type, KEY_POWER, 1); input_sync(this_input); input_event(this_input, type, KEY_POWER, 0); input_sync(this_input); break; case 3 : // for stand by and wake up input_event(this_input, type, KEY_POWER, 1); input_sync(this_input); input_event(this_input, type, KEY_POWER, 0); input_sync(this_input); input_event(this_input, type, KEY_POWER, 1); input_sync(this_input); input_event(this_input, type, KEY_POWER, 0); input_sync(this_input); break; default: break; } } EXPORT_SYMBOL(this_input_report_event); ...... static int __devinit gpio_keys_probe(struct platform_device *pdev) { ...... input = input_allocate_device(); this_input = input; //添加这一行,为了能向上发送按键事件 if (!ddata || !input) { dev_err(dev, "failed to allocate state\n"); error = -ENOMEM; goto fail1; } ...... } ...... 三、板级文件注册按键设备: cat arch/arm/mach-mx6/board-mx6q_sabresd.c ...... //这里随意改的,只要不和其他引脚有冲突就行 #define SABRESD_POWER_OFF IMX_GPIO_NR(3, 29) ...... static struct gpio_keys_button new_sabresd_buttons[] = { //GPIO_BUTTON(SABRESD_VOLUME_UP, KEY_VOLUMEUP, 1, "volume-up", 0, 1), //GPIO_BUTTON(SABRESD_VOLUME_DN, KEY_VOLUMEDOWN, 1, "volume-down", 0, 1), GPIO_BUTTON(SABRESD_POWER_OFF, KEY_POWER, 1, "power-key", 1, 1), }; ...... 四、添加shutdown设备节点,便于控制: cat drivers/input/keyboard/shutdown.c #include <linux/module.h> #include <linux/fs.h> #include <linux/gpio.h> #include <linux/miscdevice.h> /** switch case are in gpio_key.c */ #define THIS_INPUT_SHUTDOWN_SOFTWARE 1 #define THIS_INPUT_STANBY_SOFTWARE 2 #define THIS_INPUT_STANBY_AND_WAKEUP_SOFTWARE 3 extern void this_input_report_event(int mode); static int shutdown_open(struct inode *inode, struct file *file) { return 0; } static int shutdown_close(struct inode *inode, struct file *file) { return 0; } static ssize_t shutdown_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { return 0; } long shutdown_ioctl(struct file * file, unsigned int cmd, unsigned long arg) { this_input_report_event(cmd); } struct file_operations shutdown_fops = { .owner = THIS_MODULE, .open = shutdown_open, .release = shutdown_close, .read = shutdown_read, .unlocked_ioctl = shutdown_ioctl, }; struct miscdevice shutdown_misc = { .minor = MISC_DYNAMIC_MINOR, .name = "shutdown", .fops = &shutdown_fops, }; int __init shutdown_init(void) { int ret; ret = misc_register(&shutdown_misc); if(ret) printk("register shutdown FAILED!\n"); return ret; } void __exit shutdown_exit(void) { misc_deregister(&shutdown_misc); } module_init(shutdown_init); module_exit(shutdown_exit); MODULE_LICENSE("GPL"); 五、关闭关机时的提示框: cat frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java ...... public class PhoneWindowManager implements WindowManagerPolicy { ...... private final Runnable mPowerLongPress = new Runnable() { @Override public void run() { // The context isn't read if (mLongPressOnPowerBehavior < 0) { mLongPressOnPowerBehavior = mContext.getResources().getInteger( com.android.internal.R.integer.config_longPressOnPowerBehavior); } int resolvedBehavior = mLongPressOnPowerBehavior; if (FactoryTest.isLongPressOnPowerOffEnabled()) { resolvedBehavior = LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM; } switch (resolvedBehavior) { case LONG_PRESS_POWER_NOTHING: break; case LONG_PRESS_POWER_GLOBAL_ACTIONS: mPowerKeyHandled = true; if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) { performAuditoryFeedbackForAccessibilityIfNeed(); } sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); //注释这一样 //showGlobalActionsDialog(); //添加这一行 mWindowManagerFuncs.shutdown(resolvedBehavior == LONG_PRESS_POWER_SHUT_OFF); break; case LONG_PRESS_POWER_SHUT_OFF: case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM: mPowerKeyHandled = true; performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); mWindowManagerFuncs.shutdown(resolvedBehavior == LONG_PRESS_POWER_SHUT_OFF); break; } } }; ...... } ...... 六、关闭watchdog: cat drivers/watchdog/imx2_wdt.c ...... // 这里主要是I.MX6的watchdog是一旦打开,就不能关闭的,所以在这里想了个办法,堵住,看上去堵住了 static void imx2_wdt_shutdown(struct platform_device *pdev) { if (test_bit(IMX2_WDT_STATUS_STARTED, &imx2_wdt.status)) { /* we are running, we need to delete the timer but will give * max timeout before reboot will take place */ del_timer_sync(&imx2_wdt.timer); //注释这两行 //imx2_wdt_set_timeout(IMX2_WDT_MAX_TIME); //imx2_wdt_ping(); //添加这两行 printk("imx2_wdt_stop();"); imx2_wdt_stop(); //再次执行上面的流程,主要为因为有时候不是仅仅一次不是很稳定 del_timer_sync(&imx2_wdt.timer); imx2_wdt_stop(); dev_crit(imx2_wdt_miscdev.parent, "Device shutdown: Expect reboot!\n"); } } ...... 七、使用JNI进行测试: /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_android_shutdown_Shutdown */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "android/log.h" #include <sys/reboot.h> static const char *TAG="GPIO_SHUTDOWN"; #define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args) #define THIS_INPUT_SHUTDOWN_SOFTWARE 1 #define THIS_INPUT_STANBY_SOFTWARE 2 #define THIS_INPUT_STANBY_AND_WAKEUP_SOFTWARE 3 /* * Class: com_android_shutdown_Shutdown * Method: shutdown * Signature: ()V */ JNIEXPORT void JNICALL Java_com_android_shutdown_Shutdown_shutdown (JNIEnv * env, jobject thiz) { int fd = open("/dev/shutdown", O_RDWR); if (fd < 0) { perror("shutdown system faild.\n"); } ioctl(fd, THIS_INPUT_SHUTDOWN_SOFTWARE, 0); close(fd); } 八、JNI对应的Java文件: cat shutdown.java package com.android.shutdown; public class Shutdown { native static public void shutdown(); static { System.loadLibrary("shutdown"); } }