注:本操作基于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, >1x_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;
...
}
网友评论