• 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
    ");
                    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!
    ");
            
                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!
    ");
                }
            }
            ......
    
    七、使用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.
    ");
            }
        
            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");
            }
        }
  • 相关阅读:
    教你写能被舒服舒服又舒服地调用的iOS库
    无比迅速敏捷地开发iOS超精美控件
    iOS中UIlabel多行文本展示使用小结
    诸葛亮诫子书
    保留开阔的心灵空间
    iOS长按手势列表拖拽功能实现
    iOS通知使用小结
    真正的成熟
    生活的常态
    记一次LNMP 502问题的解决 (Nginx 、php、php-fpm)
  • 原文地址:https://www.cnblogs.com/zengjfgit/p/5060522.html
Copyright © 2020-2023  润新知