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");
        }
    }

 

时间: 2024-10-01 20:30:14

I.MX6 shutdown by software的相关文章

I.MX6 Android shutdown shell command

/******************************************************************************* * I.MX6 Android shutdown shell command * 说明: * 想在I.MX6上执行shell关机命令,不过效果貌似不是很好,开关键多按两下又亮了. * * 2016-7-25 深圳 南山平山村 曾剑锋 ****************************************************

I.MX6 android shutdown 内核崩溃

/**************************************************************************** * I.MX6 android shutdown 内核崩溃 * 说明: * 本文主要是记录解决I.MX6的关机会进入halt模式,导致内核崩溃. * * 2016-3-24 深圳 南山平山村 曾剑锋 ************************************************************************

I.MX6 android 移除shutdown功能

/************************************************************************ * I.MX6 android 移除shutdown功能 * 说明: * 有时候,我们可能会只是不需要android中的shutdown功能. * * 2016-3-17 深圳 南山平山村 曾剑锋 ***********************************************************************/ cat

Automating Database Startup and Shutdown(开机启动和关闭oracle)

參考:http://download.oracle.com/docs/pdf/B10812_02.pdf Use the dbstart and dbshut scripts to automate database startup and shutdown. Perform the following tasks to set up these scripts so that they are called at system startup and shutdown. Perform the

I.MX6 Manufacturing Tool V2 (MFGTool2) Update Command List (UCL) User Guide translate

  Manufacturing Tool V2 (MFGTool2)  Update Command List (UCL) User Guide     Contents(目录) Contents(目录)                                                        1 1 Overview(概述)                                                      2 2 UTP mode operation

I.MX6 Linux I2C device&amp; driver hacking

/******************************************************************************************* * I.MX6 Linux I2C device& driver hacking * 声明: * 1. 本文主要是对Linux I2C驱动进行代码跟踪,主要是为了能够对I2C驱动框架有个全面的了解: * 2. 本文源代码来自myzr_android4_2_2_1_1_0.tar.bz2: * 3. 如果你有兴趣,

I.MX6 U-boot imxotp MAC address 写入

/***************************************************************************** * I.MX6 U-boot imxotp MAC address 写入 * 说明: * I.MX6DL默认是没有MAC地址的,从代码来看,是由自动生成MAC地址的,但是在 * U-boot阶段是可以通过imxotp进行MAC地址的写入的. * * 2016-6-24 深圳 南山平山村 曾剑锋 ***********************

I.MX6 各模块 clock 查询

/********************************************************************* * I.MX6 各模块 clock 查询 * 说明: * 今天在查资料的时候无意中发现了查看内核时钟频率的方法,这东西 * 我一直以为不能查,只能通过查看源代码来看. * * 2016-8-1 深圳 南山平山村 曾剑锋 ********************************************************************/

I.MX6 Linux udev porting

/*********************************************************************** * I.MX6 Linux udev porting * 声明: * 在嵌入式产品上,我们可以使用mdev来解决热插拔的问题,同时也经常看到 * udev,所以尝试来移植一下,但是最终发现她会丢失内核阶段产生的uevent, * 这导致无法生成内核阶段产生的设备节点,目前采用了mdev来做完成内核阶段的 * 设备节点生成,之后使用udev完成热插拔,这