美文网首页
GT5688的手势唤醒执行流程分析

GT5688的手势唤醒执行流程分析

作者: 加菲猫Jack | 来源:发表于2019-03-27 22:26 被阅读0次

    注:本操作基于gt1x_1.6版本代码

    1、首先打开手势唤醒功能

    CONFIG_GTP_GESTURE_WAKEUP  =1
    

    同时,static long gt1x_ioctl函数中,gsture_enabled也要置1。

    int gesture_enabled = 1;    /* module switch */
    

    然而修改上面之后发现还是进入gesture_disabled。解决方案是需要修改如下两个位置for debug。gestures_flag值要从0x00改成0xFF,驱动调通以后这两个位置需要改成0、交由App控制

    void gt1x_gesture_debug(int on) 
    {
        if (on) {
            gesture_enabled = 1;
            memset(gestures_flag, 0xFF, sizeof(gestures_flag));
        } else {
            gesture_enabled = 0;
            memset(gestures_flag, 0xFF, sizeof(gestures_flag));
            gesture_doze_status = DOZE_DISABLED;
        }
        GTP_DEBUG("Gesture debug %s", on ? "on":"off");
    }
    

    2、手势部分驱动执行流程:
    2-1、手势init,按下开机键或者息屏后整机进入待机休眠,驱动由正常模式转到doze模式
    创建gseture节点

    s32 gt1x_init_node(void)
    {
    ...
        proc_entry = proc_create(GESTURE_NODE, 0666, NULL, &gt1x_fops);
        if (proc_entry == NULL) {
            GTP_ERROR("CAN't create proc entry /proc/%s.", GESTURE_NODE);
            return -1;
        } else {
            GTP_INFO("Created proc entry /proc/%s.", GESTURE_NODE);
        }
    #endif
    

    向系统注册KEY_GES_CUSTOM这个电源事件

    #ifdef CONFIG_GTP_GESTURE_WAKEUP
        input_set_capability(tpd->dev, EV_KEY, KEY_GES_CUSTOM);
           input_set_capability(tpd->dev, EV_KEY, KEY_GES_REGULAR);
    #endif
    

    驱动由正常模式转到doze模式

    #ifdef CONFIG_GTP_GESTURE_WAKEUP
        gesture_clear_wakeup_data();
        if (gesture_enabled) {
            gesture_enter_doze();
            gt1x_irq_enable();
            gt1x_halt = 0;
        } else
    #endif
    
    //系统进入休眠
    int gt1x_suspend(void)
       {
           s32 ret = -1;
        if (update_info.status) {
            return 0;
        }
        GTP_INFO("Suspend start...");
    }
    //关闭中断
    void gt1x_irq_disable(void)
    {
        unsigned long flag;
    
        spin_lock_irqsave(&irq_lock, flag);
        if (tpd_irq_flag) {
            GTP_INFO("gt1x_irq_disable is %d", tpd_irq_flag);
            tpd_irq_flag = 0;
        }
        spin_unlock_irqrestore(&irq_lock, flag);
    }
    //读取IC状态
    static ssize_t gt1x_gesture_data_write(struct file *filp, const char __user * buff, size_t len, loff_t * off)
    {
        s32 ret = 0;
    
        GTP_DEBUG_FUNC();
    
        ret = copy_from_user(&gesture_enabled, buff, 1);
        if (ret) {
            GTP_ERROR("copy_from_user failed.");
            return -EPERM;
        }
    
        GTP_DEBUG("gesture enabled:%x, ret:%d", gesture_enabled, ret);
    
        return len;
    }
    //给0x8040发送8,IC进入最小化手势doze状态
    int gesture_enter_doze(void)
    {
        int retry = 0;
    
        GTP_DEBUG_FUNC();
        GTP_DEBUG("Entering doze mode...");
        while (retry++ < 5) {
            if (!gt1x_send_cmd(0x08, 0)) {
                gesture_doze_status = DOZE_ENABLED;
                GTP_DEBUG("Working in doze mode!");
                return 0;
            }
            msleep(10);
        }
        GTP_ERROR("Send doze cmd failed.");
        return -1;
    }
    

    2-2、唤醒流程:

    #ifdef CONFIG_GTP_GESTURE_WAKEUP
            ret = gesture_event_handler(tpd->dev);
            if (ret >= 0) {
                gt1x_irq_enable();
                mutex_unlock(&i2c_access);
                continue;
            }
    #endif
    
    

    读取gesture寄存器状态

    static ssize_t gt1x_gesture_data_read(struct file *file, char __user * page, size_t size, loff_t * ppos)
    {
        s32 ret = -1;
        GTP_DEBUG("visit gt1x_gesture_data_read. ppos:%d", (int)*ppos);
        if (*ppos) {
            return 0;
        }
        if (size == 4) {
            ret = copy_to_user(((u8 __user *) page), "GT1X", 4);
            return 4;
        }
        ret = simple_read_from_buffer(page, size, ppos, &gesture_data, sizeof(gesture_data));
    
        GTP_DEBUG("Got the gesture data.");
        return ret;
    }
    

    按键处理函数中对手势坐标对比

    s32 gesture_event_handler(struct input_dev * dev)
    {
    
    //做一些初始化,为为读取坐标等做准备
        u8 doze_buf[4] = { 0 }, ges_type;
        static int err_flag1 = 0, err_flag2 = 0;
        int len, extra_len, need_chk;
        unsigned int key_code;
        s32 ret = 0;
    
        if (DOZE_ENABLED != gesture_doze_status) {
            return -1;
        }
        
        /** package: -head 4B + track points + extra info- 
            * - head -
            *  doze_buf[0]: gesture type, 
            *  doze_buf[1]: number of gesture points ,
            *  doze_buf[2]: protocol type, 
            *  doze_buf[3]: gesture extra data length.
            */
    
    //对0x814B寄存器进行读取操作
        ret = gt1x_i2c_read(GTP_REG_WAKEUP_GESTURE, doze_buf, 4);
        if (ret < 0) {
            return 0;
        }    
        ges_type = doze_buf[0];
        len = doze_buf[1];
        need_chk = doze_buf[2] & 0x80;
        extra_len = doze_buf[3];
    //读取到寄存器获取到的值    
        GTP_DEBUG("0x%x = 0x%02X,0x%02X,0x%02X,0x%02X", GTP_REG_WAKEUP_GESTURE,
            doze_buf[0], doze_buf[1], doze_buf[2], doze_buf[3]);
        //对获取到的报点验证
        if (len > GESTURE_MAX_POINT_COUNT) {
            GTP_ERROR("Gesture contain too many points!(%d)", len);
            len = GESTURE_MAX_POINT_COUNT;
        }
    
        if (extra_len > 32) {
            GTP_ERROR("Gesture contain too many extra data!(%d)", extra_len);
            extra_len = 32;
        }
    

    检测手指轨迹,符合条件即唤醒系统

        /* get gesture extra info */
        if (extra_len >= 0) {
            u8 ges_data[extra_len + 1];
            
            /* head 4 + extra data * 4 + chksum 1 */
            ret = gt1x_i2c_read(GTP_REG_WAKEUP_GESTURE + 4,
                ges_data, extra_len + 1);
            if (ret < 0) {
                GTP_ERROR("Read extra gesture data failed.");
                return 0;
            }
            
            if (likely(need_chk)) { /* calc checksum */
                bool val;
    
                ges_data[extra_len] += doze_buf[0] + doze_buf[1]
                    + doze_buf[2] + doze_buf[3];
    
                val = calc_checksum(ges_data, extra_len + 1, CHKBITS_8);
                if (unlikely(!val)) { /* check failed */
                    GTP_ERROR("Gesture checksum error.");
                    if (err_flag1) {
                        err_flag1 = 0;
                        ret = 0;
                        goto clear_reg;
                    } else {
                        /* just return 0 without clear reg, 
                                        this will receive another int, we
                                        check the data in the next frame */
                        err_flag1 = 1;
                        return 0;
                    }
                }
                
                err_flag1 = 0;
            }
            
            mutex_lock(&gesture_data_mutex);
            memcpy(&gesture_data.data[4 + len * 4], ges_data, extra_len);
            mutex_unlock(&gesture_data_mutex);
        }
       /* gt1x_gesture_debug里的gestures_flag内存值要为0xFF,否则会一直进入以下打印:Gesture has been disabled*/
        /* check gesture type (if available?) */
        if (ges_type == 0 || !QUERYBIT(gestures_flag, ges_type)) {
            GTP_INFO("Gesture[0x%02X] has been disabled.", doze_buf[0]);
            doze_buf[0] = 0x00;
            gt1x_i2c_write(GTP_REG_WAKEUP_GESTURE, doze_buf, 1);
            gesture_enter_doze();
            return 0;
        }
    
        /* get gesture point data */
        if (len > 0) { /* coor num * 4 + chksum 2*/
            u8 ges_data[len * 4 + 2];
    
            ret = gt1x_i2c_read(GES_BUFFER_ADDR, ges_data, len * 4);
            if (ret < 0) {
                GTP_ERROR("Read gesture data failed.");
                return 0;
            }
            
            /* checksum reg for gesture point data */
            ret = gt1x_i2c_read(0x819F, &ges_data[len * 4], 2);
            if (ret < 0) {
                GTP_ERROR("Read gesture data failed.");
                return 0;
            }
            
            if (likely(need_chk)) {
                bool val = calc_checksum(ges_data,
                   len * 4 + 2, CHKBITS_16);
                if (unlikely(!val)) { /* check failed */
                    GTP_ERROR("Gesture checksum error.");
                    if (err_flag2) {
                        err_flag2 = 0;
                        ret = 0;
                        goto clear_reg;
                    } else {
                        err_flag2 = 1;
                        return 0;
                    }
                }
                
                err_flag2 = 0;
            }
            
            mutex_lock(&gesture_data_mutex);
            memcpy(&gesture_data.data[4], ges_data, len * 4);
            mutex_unlock(&gesture_data_mutex);
        }
    
        mutex_lock(&gesture_data_mutex);
        gesture_data.data[0] = ges_type;    // gesture type
        gesture_data.data[1] = len;         // gesture points number
        gesture_data.data[2] = doze_buf[2] & 0x7F; // protocol type
        gesture_data.data[3] = extra_len;   // gesture date length
        mutex_unlock(&gesture_data_mutex);
    
        //获取键值,触发唤醒键来上报唤醒屏幕,清除0x814B状态
        /* get key code */
        key_code = ges_type < 16? KEY_GES_CUSTOM : KEY_GES_REGULAR;
        GTP_DEBUG("Gesture: 0x%02X, points: %d", doze_buf[0], doze_buf[1]);
    
        input_report_key(dev, key_code, 1);
        input_sync(dev);
        input_report_key(dev, key_code, 0);
        input_sync(dev);
    
    clear_reg:
        doze_buf[0] = 0; // clear ges flag
        gt1x_i2c_write(GTP_REG_WAKEUP_GESTURE, doze_buf, 1);
        return ret;
    }
    
    endif // GTP_GESTURE_WAKEUP
    

    移除gesture_node

    remove_proc_entry(GESTURE_NODE, NULL);
    

    唤醒TP

    static void tpd_resume(struct device *h)
    

    唤醒系统

    static s32 gt1x_wakeup_sleep(void)
    {
        GTP_DEBUG("Wake up begin.");
        gt1x_irq_disable();//关闭中断
        while (retry++ < 2) {
    #ifdef CONFIG_GTP_GESTURE_WAKEUP
            if (gesture_enabled) {
                gesture_doze_status = DOZE_DISABLED;//doze状态更新为disabled
                ret = gt1x_reset_guitar();//复位
                if(!ret) {
                    break;
                }
            } else
    #endif
        /* wake up through int port */
              //使用中断GPIO唤醒          
      GTP_GPIO_OUTPUT(GTP_INT_PORT, gt1x_wakeup_level);
                msleep(5);
    
                /* Synchronize int IO */
                GTP_GPIO_OUTPUT(GTP_INT_PORT, 0);
                msleep(50);
                GTP_GPIO_AS_INT(GTP_INT_PORT);
                flag = 1;
    ...
    }
    

    相关文章

      网友评论

          本文标题:GT5688的手势唤醒执行流程分析

          本文链接:https://www.haomeiwen.com/subject/kxmuyqtx.html