/******************************************************* Function: Goodix tool write function. Input: standard proc write function param. Output: Return write length. ********************************************************/ static s32 goodix_tool_write(struct file *filp, const char __user *buff, unsigned long len, void *data) { s32 ret = 0; GTP_DEBUG_FUNC(); GTP_DEBUG_ARRAY((u8*)buff, len); ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH); if(ret) { GTP_ERROR("copy_from_user failed."); } GTP_DEBUG("wr :0x%02x.", cmd_head.wr); GTP_DEBUG("flag:0x%02x.", cmd_head.flag); GTP_DEBUG("flag addr:0x%02x%02x.", cmd_head.flag_addr[0], cmd_head.flag_addr[1]); GTP_DEBUG("flag val:0x%02x.", cmd_head.flag_val); GTP_DEBUG("flag rel:0x%02x.", cmd_head.flag_relation); GTP_DEBUG("circle :%d.", (s32)cmd_head.circle); GTP_DEBUG("times :%d.", (s32)cmd_head.times); GTP_DEBUG("retry :%d.", (s32)cmd_head.retry); GTP_DEBUG("delay :%d.", (s32)cmd_head.delay); GTP_DEBUG("data len:%d.", (s32)cmd_head.data_len); GTP_DEBUG("addr len:%d.", (s32)cmd_head.addr_len); GTP_DEBUG("addr:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]); GTP_DEBUG("len:%d.", (s32)len); GTP_DEBUG("buf[20]:0x%02x.", buff[CMD_HEAD_LENGTH]); if (1 == cmd_head.wr) { // copy_from_user(&cmd_head.data[cmd_head.addr_len], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); if(ret) { GTP_ERROR("copy_from_user failed."); } memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.addr, cmd_head.addr_len); GTP_DEBUG_ARRAY(cmd_head.data, cmd_head.data_len + cmd_head.addr_len); GTP_DEBUG_ARRAY((u8*)&buff[CMD_HEAD_LENGTH], cmd_head.data_len); if (1 == cmd_head.flag) { if (FAIL == comfirm()) { GTP_ERROR("[WRITE]Comfirm fail!"); return FAIL; } } else if (2 == cmd_head.flag) { //Need interrupt! } if (tool_i2c_write(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.data_len + cmd_head.addr_len) <= 0) { GTP_ERROR("[WRITE]Write data failed!"); return FAIL; } GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],cmd_head.data_len + cmd_head.addr_len); if (cmd_head.delay) { msleep(cmd_head.delay); } return cmd_head.data_len + CMD_HEAD_LENGTH; } else if (3 == cmd_head.wr) { //Write ic type ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); if(ret) { GTP_ERROR("copy_from_user failed."); } memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); register_i2c_func(); return cmd_head.data_len + CMD_HEAD_LENGTH; } else if (5 == cmd_head.wr) { //memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); return cmd_head.data_len + CMD_HEAD_LENGTH; } else if (7 == cmd_head.wr) { //disable irq! gtp_irq_disable(i2c_get_clientdata(gt_client)); #if GTP_ESD_PROTECT gtp_esd_switch(gt_client, SWITCH_OFF); #endif return CMD_HEAD_LENGTH; } else if (9 == cmd_head.wr) { //enable irq! gtp_irq_enable(i2c_get_clientdata(gt_client)); #if GTP_ESD_PROTECT gtp_esd_switch(gt_client, SWITCH_ON); #endif return CMD_HEAD_LENGTH; } else if(17 == cmd_head.wr) { struct goodix_ts_data *ts = i2c_get_clientdata(gt_client); ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); if(ret) { GTP_DEBUG("copy_from_user failed."); } if(cmd_head.data[GTP_ADDR_LENGTH]) { GTP_DEBUG("gtp enter rawdiff."); ts->gtp_rawdiff_mode = true; } else { ts->gtp_rawdiff_mode = false; GTP_DEBUG("gtp leave rawdiff."); } return CMD_HEAD_LENGTH; } #ifdef UPDATE_FUNCTIONS else if (11 == cmd_head.wr) { //Enter update mode! if (FAIL == gup_enter_update_mode(gt_client)) { return FAIL; } } else if (13 == cmd_head.wr) { //Leave update mode! gup_leave_update_mode(); } else if (15 == cmd_head.wr) { //Update firmware! show_len = 0; total_len = 0; memset(cmd_head.data, 0, cmd_head.data_len + 1); memcpy(cmd_head.data, &buff[CMD_HEAD_LENGTH], cmd_head.data_len); if (FAIL == gup_update_proc((void*)cmd_head.data)) { return FAIL; } } #endif return CMD_HEAD_LENGTH; }
/******************************************************* Function: Touch down report function. Input: ts:private data. id:tracking id. x:input x. y:input y. w:input weight. Output: None. *******************************************************/ static void gtp_touch_down(struct goodix_ts_data* ts,s32 id,s32 x,s32 y,s32 w) { if (goodix_pdata->xpol) x = ts->abs_x_max - x; if (goodix_pdata->ypol) y = ts->abs_y_max - y; #if MAL_EDGE_CAL_PERCENT u8 i, j; u16 max_res, cal_range, cal_max_offset, cal_offset; u16 * curr_res; for (i = 0; i < 2; i++) { max_res = (i == 0) ? ts->abs_x_max : ts->abs_y_max; curr_res = (i == 0) ? &x : &y; cal_range = max_res * MAL_EDGE_CAL_PERCENT / 100; cal_max_offset = cal_range / MAL_EDGE_CAL_OFFSET_RATE; for (j = 0; j < 2; j++) { if (j != 0) // process right end { *curr_res = max_res - *curr_res; } if (*curr_res < cal_range) { if (*curr_res < cal_max_offset) { if (*curr_res > 7) *curr_res = (*curr_res * 8 - 40) / 3; } else { cal_offset = cal_max_offset - *curr_res / MAL_EDGE_CAL_OFFSET_RATE; *curr_res += cal_offset; } } if (j != 0) { *curr_res = max_res - *curr_res; } } } GTP_DEBUG("<YLM>, max_res:%d, curr_res:%d, cal_range:%d, cal_offset:%d.", max_res, *curr_res, cal_range, cal_offset); #endif #if MAL_FIX_EDGE_POINT if (x < MAL_FIX_EDGE_POINT) x = MAL_FIX_EDGE_POINT; if (x > ts->abs_x_max - MAL_FIX_EDGE_POINT) x = ts->abs_x_max - MAL_FIX_EDGE_POINT; if (y < MAL_FIX_EDGE_POINT) y = MAL_FIX_EDGE_POINT; if (y > ts->abs_y_max - MAL_FIX_EDGE_POINT) y = ts->abs_y_max - MAL_FIX_EDGE_POINT; #endif #if GTP_CHANGE_X2Y GTP_SWAP(x, y); #else if (goodix_pdata->swap_xy) GTP_SWAP(x, y); #endif #if GTP_ICS_SLOT_REPORT input_mt_slot(ts->input_dev, id); input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id); input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); input_report_abs(ts->input_dev, ABS_MT_PRESSURE, w); #else input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w); input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id); input_mt_sync(ts->input_dev); #endif GTP_DEBUG("ID:%d, X:%d, Y:%d, W:%d", id, x, y, w); }
/******************************************************* Function: Goodix tool read function. Input: standard proc read function param. Output: Return read length. ********************************************************/ static s32 goodix_tool_read( char *page, char **start, off_t off, int count, int *eof, void *data ) { GTP_DEBUG_FUNC(); if (cmd_head.wr % 2) { return FAIL; } else if (!cmd_head.wr) { u16 len = 0; s16 data_len = 0; u16 loc = 0; if (1 == cmd_head.flag) { if (FAIL == comfirm()) { GTP_ERROR("[READ]Comfirm fail!"); return FAIL; } } else if (2 == cmd_head.flag) { //Need interrupt! } memcpy(cmd_head.data, cmd_head.addr, cmd_head.addr_len); GTP_DEBUG("[CMD HEAD DATA] ADDR:0x%02x%02x\n", cmd_head.data[0], cmd_head.data[1]); GTP_DEBUG("[CMD HEAD ADDR] ADDR:0x%02x%02x\n", cmd_head.addr[0], cmd_head.addr[1]); if (cmd_head.delay) { msleep(cmd_head.delay); } data_len = cmd_head.data_len; while(data_len > 0) { if (data_len > DATA_LENGTH) { len = DATA_LENGTH; } else { len = data_len; } data_len -= DATA_LENGTH; if (tool_i2c_read(cmd_head.data, len) <= 0) { GTP_ERROR("[READ]Read data failed!"); return FAIL; } memcpy(&page[loc], &cmd_head.data[GTP_ADDR_LENGTH], len); loc += len; //GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH], len); GTP_DEBUG_ARRAY(page, len); } } else if (2 == cmd_head.wr) { // memcpy(page, "gt8", cmd_head.data_len); // memcpy(page, "GT818", 5); // page[5] = 0; GTP_DEBUG("Return ic type:%s len:%d\n", page, (s32)cmd_head.data_len); return cmd_head.data_len; //return sizeof(IC_TYPE_NAME); } else if (4 == cmd_head.wr) { page[0] = show_len >> 8; page[1] = show_len & 0xff; page[2] = total_len >> 8; page[3] = total_len & 0xff; return cmd_head.data_len; }
/******************************************************* Function: GTP initialize function. Input: ts: i2c client private struct. Output: Executive outcomes.0---succeed. *******************************************************/ s32 gtp_init_panel(struct goodix_ts_data *ts) { s32 ret = -1; u8 rd_cfg_buf[4]; int index = -1; u8 cfg_info_group1[] = CTP_CFG_GROUP_DPT1;//dpt yiju u8 cfg_info_group2[] = CTP_CFG_GROUP; u8 * send_cfg_buf[2] = {cfg_info_group1,cfg_info_group2}; #if 0 u8 cfg_info_group1[] = CTP_CFG_GROUP1; u8 cfg_info_group2[] = CTP_CFG_GROUP2; u8 cfg_info_group3[] = CTP_CFG_GROUP3; u8 * send_cfg_buf[3] = {cfg_info_group1, cfg_info_group2, cfg_info_group3}; u8 cfg_info_len[3] = {sizeof(cfg_info_group1)/sizeof(cfg_info_group1[0]), sizeof(cfg_info_group2)/sizeof(cfg_info_group2[0]), sizeof(cfg_info_group3)/sizeof(cfg_info_group3[0])}; GTP_DEBUG("len1=%d,len2=%d,len3=%d",cfg_info_len[0],cfg_info_len[1],cfg_info_len[2]); if ((!cfg_info_len[1])&&(!cfg_info_len[2])) { rd_cfg_buf[GTP_ADDR_LENGTH] = 0; } else { rd_cfg_buf[0] = (u8)(GTP_REG_SENSOR_ID>>8); rd_cfg_buf[1] = (u8)GTP_REG_SENSOR_ID; ret=gtp_i2c_read(ts->client, rd_cfg_buf, 3); if (ret <= 0) { GTP_ERROR("Read SENSOR ID failed,default use group1 config!"); rd_cfg_buf[GTP_ADDR_LENGTH] = 0; } rd_cfg_buf[GTP_ADDR_LENGTH] &= 0x03; } GTP_DEBUG("SENSOR ID:%d", rd_cfg_buf[GTP_ADDR_LENGTH]); memcpy(config, send_cfg_buf[rd_cfg_buf[GTP_ADDR_LENGTH]], (GTP_CONFIG_LENGTH+GTP_ADDR_LENGTH)); #endif rd_cfg_buf[0] = (u8)(GTP_REG_SENSOR_ID>>8); rd_cfg_buf[1] = (u8)GTP_REG_SENSOR_ID; ret=gtp_i2c_read(ts->client, rd_cfg_buf, 3); if (ret <= 0) { printk("Read SENSOR ID failed,default use group1 config!"); rd_cfg_buf[GTP_ADDR_LENGTH] = 0; } rd_cfg_buf[GTP_ADDR_LENGTH] &= 0x03; dprintk(DEBUG_INIT, "sensor ID =%d\n\n",rd_cfg_buf[GTP_ADDR_LENGTH]); index = 0; if(rd_cfg_buf[GTP_ADDR_LENGTH] == 2) index = 6; index = 0;//gandy memcpy(config, send_cfg_buf[index], sizeof(cfg_info_group1)); #if GTP_CUSTOM_CFG config[57] &= 0xf7; if(GTP_INT_TRIGGER&0x01) { config[57] += 0x08; } config[59] = GTP_REFRESH; config[60] = GTP_MAX_TOUCH>5 ? 5 : GTP_MAX_TOUCH; config[61] = (u8)SCREEN_MAX_WIDTH; config[62] = (u8)(SCREEN_MAX_WIDTH >> 8); config[63] = (u8)SCREEN_MAX_X; config[64] = (u8)(SCREEN_MAX_Y >> 8); #endif ts->abs_x_max = (config[62]<<8) + config[61]; ts->abs_y_max = (config[64]<<8) + config[63]; ts->max_touch_num = config[60]; ts->int_trigger_type = ((config[57]>>3)&0x01); if ((!ts->abs_x_max)||(!ts->abs_y_max)||(!ts->max_touch_num)) { GTP_ERROR("GTP resolution & max_touch_num invalid, use default value!"); ts->abs_x_max = SCREEN_MAX_X; ts->abs_y_max = SCREEN_MAX_Y; ts->max_touch_num = GTP_MAX_TOUCH; } ret = gtp_send_cfg(ts->client); if (ret) { printk("Send config error."); } msleep(10); return 0; }
static int gt91xx_config_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) { s32 ret = 0; char temp[16] = {0}; // for store special format cmd char mode_str[8] = {0}; unsigned int mode; u8 buf[1]; GTP_DEBUG("write count %ld\n", count); if (count > GTP_CONFIG_MAX_LENGTH) { GTP_ERROR("size not match [%d:%ld]\n", GTP_CONFIG_MAX_LENGTH, count); return -EFAULT; } if (copy_from_user(&config[2], buffer, count)) { GTP_ERROR("copy from user fail\n"); return -EFAULT; } /**********************************************/ /* for store special format cmd */ if (copy_from_user(temp, buffer, sizeof(temp))) { GTP_ERROR("copy from user fail 2\n"); return -EFAULT; } sscanf(temp, "%s %d", (char *)&mode_str, &mode); if(strcmp(mode_str, "switch") == 0) { if(mode == 0)// turn off tpd_off(); else if(mode == 1)//turn on tpd_on(); else GTP_ERROR("error mode :%d\n", mode); return count; } //force clear config if(strcmp(mode_str, "clear_config") == 0) { GTP_INFO("Force clear config\n"); buf[0] = 0x10; ret = i2c_write_bytes(i2c_client_point, GTP_REG_SLEEP, buf, 1); return count; } /***********clk operate reseved****************/ /**********************************************/ ret = gtp_send_cfg(i2c_client_point); abs_x_max = (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC]; abs_y_max = (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2]; int_type = (config[TRIGGER_LOC]) & 0x03; if (ret < 0) { GTP_ERROR("send config failed."); } return count; }
//static s32 goodix_tool_write(struct file *filp, const char __user *buff, unsigned long len, void *data) ssize_t goodix_tool_write(struct file *filp, const char __user *buff, size_t len, loff_t *off) { s32 ret = 0; GTP_DEBUG_FUNC(); GTP_DEBUG_ARRAY((u8*)buff, len); ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH); if(ret) { GTP_ERROR("copy_from_user failed."); return -EPERM; } GTP_DEBUG("[Operation]wr: %02X", cmd_head.wr); GTP_DEBUG("[Flag]flag: %02X, addr: %02X%02X, value: %02X, relation: %02X", cmd_head.flag, cmd_head.flag_addr[0], cmd_head.flag_addr[1], cmd_head.flag_val, cmd_head.flag_relation); GTP_DEBUG("[Retry]circle: %d, times: %d, retry: %d, delay: %d", (s32)cmd_head.circle, (s32)cmd_head.times, (s32)cmd_head.retry, (s32)cmd_head.delay); GTP_DEBUG("[Data]data len: %d, addr len: %d, addr: %02X%02X, buffer len: %d, data[0]: %02X", (s32)cmd_head.data_len, (s32)cmd_head.addr_len, cmd_head.addr[0], cmd_head.addr[1], (s32)len, buff[CMD_HEAD_LENGTH]); if (1 == cmd_head.wr) { ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); if(ret) { GTP_ERROR("copy_from_user failed."); return -EPERM; } memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.addr, cmd_head.addr_len); GTP_DEBUG_ARRAY(cmd_head.data, cmd_head.data_len + cmd_head.addr_len); GTP_DEBUG_ARRAY((u8*)&buff[CMD_HEAD_LENGTH], cmd_head.data_len); if (1 == cmd_head.flag) { if (FAIL == comfirm()) { GTP_ERROR("[WRITE]Comfirm fail!"); return -EPERM; } } else if (2 == cmd_head.flag) { //Need interrupt! } if (tool_i2c_write(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], cmd_head.data_len + cmd_head.addr_len) <= 0) { GTP_ERROR("[WRITE]Write data failed!"); return -EPERM; } GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],cmd_head.data_len + cmd_head.addr_len); if (cmd_head.delay) { msleep(cmd_head.delay); } } else if (3 == cmd_head.wr) //Write ic type { ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); if(ret) { GTP_ERROR("copy_from_user failed."); return -EPERM; } memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); register_i2c_func(); } else if (5 == cmd_head.wr) { //memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); } else if (7 == cmd_head.wr)//disable irq! { gtp_irq_disable(i2c_get_clientdata(gt_client)); #if GTP_ESD_PROTECT gtp_esd_switch(gt_client, SWITCH_OFF); #endif } else if (9 == cmd_head.wr) //enable irq! { gtp_irq_enable(i2c_get_clientdata(gt_client)); #if GTP_ESD_PROTECT gtp_esd_switch(gt_client, SWITCH_ON); #endif } else if(17 == cmd_head.wr) { struct goodix_ts_data *ts = i2c_get_clientdata(gt_client); ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); if(ret) { GTP_DEBUG("copy_from_user failed."); return -EPERM; } if(cmd_head.data[GTP_ADDR_LENGTH]) { GTP_INFO("gtp enter rawdiff."); ts->gtp_rawdiff_mode = true; } else { ts->gtp_rawdiff_mode = false; GTP_INFO("gtp leave rawdiff."); } } #ifdef UPDATE_FUNCTIONS else if (11 == cmd_head.wr)//Enter update mode! { if (FAIL == gup_enter_update_mode(gt_client)) { return -EPERM; } } else if (13 == cmd_head.wr)//Leave update mode! { gup_leave_update_mode(); } else if (15 == cmd_head.wr) //Update firmware! { show_len = 0; total_len = 0; memset(cmd_head.data, 0, cmd_head.data_len + 1); memcpy(cmd_head.data, &buff[CMD_HEAD_LENGTH], cmd_head.data_len); if (FAIL == gup_update_proc((void*)cmd_head.data)) { return -EPERM; } } #endif return len; }
//static s32 goodix_tool_read( char *page, char **start, off_t off, int count, int *eof, void *data ) ssize_t goodix_tool_read(struct file *file, char __user *page, size_t size, loff_t *ppos) { s32 ret = 0; GTP_DEBUG_FUNC(); if (*ppos) // ADB call again { //GTP_DEBUG("[HEAD]wr: %d", cmd_head.wr); //GTP_DEBUG("[PARAM]size: %d, *ppos: %d", size, (int)*ppos); //GTP_DEBUG("[TOOL_READ]ADB call again, return it."); return 0; } if (cmd_head.wr % 2) { return -EPERM; } else if (!cmd_head.wr) { u16 len = 0; s16 data_len = 0; u16 loc = 0; if (1 == cmd_head.flag) { if (FAIL == comfirm()) { GTP_ERROR("[READ]Comfirm fail!"); return -EPERM; } } else if (2 == cmd_head.flag) { //Need interrupt! } memcpy(cmd_head.data, cmd_head.addr, cmd_head.addr_len); GTP_DEBUG("[CMD HEAD DATA] ADDR:0x%02x%02x.", cmd_head.data[0], cmd_head.data[1]); GTP_DEBUG("[CMD HEAD ADDR] ADDR:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]); if (cmd_head.delay) { msleep(cmd_head.delay); } data_len = cmd_head.data_len; while(data_len > 0) { if (data_len > DATA_LENGTH) { len = DATA_LENGTH; } else { len = data_len; } data_len -= len; if (tool_i2c_read(cmd_head.data, len) <= 0) { GTP_ERROR("[READ]Read data failed!"); return -EPERM; } //memcpy(&page[loc], &cmd_head.data[GTP_ADDR_LENGTH], len); ret = simple_read_from_buffer(&page[loc], size, ppos, &cmd_head.data[GTP_ADDR_LENGTH], len); if (ret < 0) { return ret; } loc += len; GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH], len); GTP_DEBUG_ARRAY(page, len); } return cmd_head.data_len; } else if (2 == cmd_head.wr) { ret = simple_read_from_buffer(page, size, ppos, IC_TYPE, sizeof(IC_TYPE)); return ret; } else if (4 == cmd_head.wr) { u8 progress_buf[4]; progress_buf[0] = show_len >> 8; progress_buf[1] = show_len & 0xff; progress_buf[2] = total_len >> 8; progress_buf[3] = total_len & 0xff; ret = simple_read_from_buffer(page, size, ppos, progress_buf, 4); return ret; }
/******************************************************* Function: Goodix tool write function. Input: standard proc write function param. Output: Return write length. ********************************************************/ static s32 gt1x_tool_write(struct file *filp, const char __user * buff, size_t len, loff_t * data) { u64 ret = 0; GTP_DEBUG_FUNC(); GTP_DEBUG_ARRAY((u8 *) buff, len); ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH); if (ret) { GTP_ERROR("copy_from_user failed."); } GTP_DEBUG("wr :0x%02x.", cmd_head.wr); /* GTP_DEBUG("flag:0x%02x.", cmd_head.flag); GTP_DEBUG("flag addr:0x%02x%02x.", cmd_head.flag_addr[0], cmd_head.flag_addr[1]); GTP_DEBUG("flag val:0x%02x.", cmd_head.flag_val); GTP_DEBUG("flag rel:0x%02x.", cmd_head.flag_relation); GTP_DEBUG("circle :%d.", (s32)cmd_head.circle); GTP_DEBUG("times :%d.", (s32)cmd_head.times); GTP_DEBUG("retry :%d.", (s32)cmd_head.retry); GTP_DEBUG("delay :%d.", (s32)cmd_head.delay); GTP_DEBUG("data len:%d.", (s32)cmd_head.data_len); GTP_DEBUG("addr len:%d.", (s32)cmd_head.addr_len); GTP_DEBUG("addr:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]); GTP_DEBUG("len:%d.", (s32)len); GTP_DEBUG("buf[20]:0x%02x.", buff[CMD_HEAD_LENGTH]); */ if (1 == cmd_head.wr) { u16 addr, data_len, pos; if (1 == cmd_head.flag) { if (comfirm()) { GTP_ERROR("[WRITE]Comfirm fail!"); return -1; } } else if (2 == cmd_head.flag) { //Need interrupt! } addr = (cmd_head.addr[0] << 8) + cmd_head.addr[1]; data_len = cmd_head.data_len; pos = 0; while (data_len > 0) { len = data_len > DATA_LENGTH ? DATA_LENGTH : data_len; ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], &buff[CMD_HEAD_LENGTH + pos], len); if (ret) { GTP_ERROR("[WRITE]copy_from_user failed."); return -1; } cmd_head.data[0] = ((addr >> 8) & 0xFF); cmd_head.data[1] = (addr & 0xFF); GTP_DEBUG_ARRAY(cmd_head.data, len + GTP_ADDR_LENGTH); if (tool_i2c_write(cmd_head.data, len + GTP_ADDR_LENGTH) <= 0) { GTP_ERROR("[WRITE]Write data failed!"); return -1; } addr += len; pos += len; data_len -= len; } if (cmd_head.delay) { msleep(cmd_head.delay); } return cmd_head.data_len + CMD_HEAD_LENGTH; } else if (3 == cmd_head.wr) { //gt1x unused
static void goodix_ts_work_func(struct work_struct *work) { struct goodix_ts_data *ts = NULL; static u16 pre_touch; static u8 pre_key; u8 end_cmd[3] = { GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF, 0 }; u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH + 1] = { GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF }; u8 touch_num = 0; u8 finger = 0; u8 key_value = 0; u8 *coor_data = NULL; s32 input_x = 0; s32 input_y = 0; s32 input_w = 0; s32 id = 0; s32 i, ret; GTP_DEBUG_FUNC(); ts = container_of(work, struct goodix_ts_data, work); if (ts->enter_update) return; ret = gtp_i2c_read(ts->client, point_data, 12); if (ret < 0) { GTP_ERROR("I2C transfer error. errno:%d\n ", ret); goto exit_work_func; } finger = point_data[GTP_ADDR_LENGTH]; if ((finger & 0x80) == 0) goto exit_work_func; touch_num = finger & 0x0f; if (touch_num > GTP_MAX_TOUCH) goto exit_work_func; if (touch_num > 1) { u8 buf[8 * GTP_MAX_TOUCH] = { (GTP_READ_COOR_ADDR + 10) >> 8, (GTP_READ_COOR_ADDR + 10) & 0xff }; ret = gtp_i2c_read(ts->client, buf, 2 + 8 * (touch_num - 1)); memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1)); } #if GTP_HAVE_TOUCH_KEY key_value = point_data[3 + 8 * touch_num]; if (key_value || pre_key) { for (i = 0; i < GTP_MAX_KEY_NUM; i++) input_report_key(ts->input_dev, touch_key_array[i], key_value & (0x01 << i)); touch_num = 0; pre_touch = 0; } #endif pre_key = key_value; GTP_DEBUG("pre_touch:%02x, finger:%02x.", pre_touch, finger); #if GTP_ICS_SLOT_REPORT if (pre_touch || touch_num) { s32 pos = 0; u16 touch_index = 0; coor_data = &point_data[3]; if (touch_num) { id = coor_data[pos] & 0x0F; touch_index |= (0x01 << id); } GTP_DEBUG("id=%d, touch_index=0x%x, pre_touch=0x%x\n",\ id, touch_index, pre_touch); for (i = 0; i < GTP_MAX_TOUCH; i++) { if (touch_index & (0x01<<i)) { input_x = coor_data[pos + 1] | coor_data[pos + 2] << 8; input_y = coor_data[pos + 3] | coor_data[pos + 4] << 8; input_w = coor_data[pos + 5] | coor_data[pos + 6] << 8; gtp_touch_down(ts, id, input_x, input_y, input_w); pre_touch |= 0x01 << i; pos += 8; id = coor_data[pos] & 0x0F; touch_index |= (0x01<<id); } else { gtp_touch_up(ts, i); pre_touch &= ~(0x01 << i); } } } #else if (touch_num) { for (i = 0; i < touch_num; i++) { coor_data = &point_data[i * 8 + 3]; id = coor_data[0] & 0x0F; input_x = coor_data[1] | coor_data[2] << 8; input_y = coor_data[3] | coor_data[4] << 8; input_w = coor_data[5] | coor_data[6] << 8; gtp_touch_down(ts, id, input_x, input_y, input_w); } } else if (pre_touch) { GTP_DEBUG("Touch Release!"); gtp_touch_up(ts, 0); } pre_touch = touch_num; input_report_key(ts->input_dev, BTN_TOUCH, (touch_num || key_value)); #endif input_sync(ts->input_dev); exit_work_func: if (!ts->gtp_rawdiff_mode) { ret = gtp_i2c_write(ts->client, end_cmd, 3); if (ret < 0) GTP_ERROR("I2C write end_cmd error!"); } if (ts->use_irq) gtp_irq_enable(ts); } static enum hrtimer_restart goodix_ts_timer_handler(struct hrtimer *timer) { struct goodix_ts_data *ts = container_of(timer, struct goodix_ts_data, timer); GTP_DEBUG_FUNC(); queue_work(goodix_wq, &ts->work); hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME + 6) * 1000000), HRTIMER_MODE_REL); return HRTIMER_NORESTART; } static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) { struct goodix_ts_data *ts = dev_id; GTP_DEBUG_FUNC(); gtp_irq_disable(ts); queue_work(goodix_wq, &ts->work); return IRQ_HANDLED; } static void gtp_int_sync(struct i2c_client *client, s32 ms) { struct gtp_platform_data *gtp_data = client->dev.platform_data; GTP_GPIO_OUTPUT(gtp_data->irq, 0); GTP_MSLEEP(ms); GTP_GPIO_AS_INT(gtp_data->irq); } void gtp_reset_guitar(struct i2c_client *client, s32 ms) { struct gtp_platform_data *gtp_data = client->dev.platform_data; GTP_DEBUG_FUNC(); /* begin select I2C slave addr */ GTP_GPIO_OUTPUT(gtp_data->reset, 0); GTP_MSLEEP(ms); GTP_GPIO_OUTPUT(gtp_data->irq, client->addr == 0x14); GTP_MSLEEP(2); GTP_GPIO_OUTPUT(gtp_data->reset, 1); /* must > 3ms */ GTP_MSLEEP(6); GTP_GPIO_AS_INPUT(gtp_data->reset); /* end select I2C slave addr */ gtp_int_sync(client, 50); } static s32 gtp_init_panel(struct goodix_ts_data *ts) { s32 ret; #if GTP_DRIVER_SEND_CFG s32 i; u8 check_sum = 0; u8 rd_cfg_buf[16]; u8 cfg_info_group1[] = CTP_CFG_GROUP1; u8 cfg_info_group2[] = CTP_CFG_GROUP2; u8 cfg_info_group3[] = CTP_CFG_GROUP3; u8 *send_cfg_buf[3] = { cfg_info_group1, cfg_info_group2, cfg_info_group3 }; u8 cfg_info_len[3] = { sizeof(cfg_info_group1) / sizeof(cfg_info_group1[0]), sizeof(cfg_info_group2) / sizeof(cfg_info_group2[0]), sizeof(cfg_info_group3) / sizeof(cfg_info_group3[0]) }; for (i = 0; i < 3; i++) { if (cfg_info_len[i] > ts->gtp_cfg_len) ts->gtp_cfg_len = cfg_info_len[i]; } GTP_DEBUG("len1=%d, len2=%d, len3=%d, send_len:%d", cfg_info_len[0], \ cfg_info_len[1], cfg_info_len[2], ts->gtp_cfg_len); if ((!cfg_info_len[1]) && (!cfg_info_len[2])) rd_cfg_buf[GTP_ADDR_LENGTH] = 0; else { rd_cfg_buf[0] = GTP_REG_SENSOR_ID >> 8; rd_cfg_buf[1] = GTP_REG_SENSOR_ID & 0xff; ret = gtp_i2c_read(ts->client, rd_cfg_buf, 3); if (ret < 0) { GTP_ERROR("Read SENSOR ID failed, " \ "default use group1 config!"); rd_cfg_buf[GTP_ADDR_LENGTH] = 0; } rd_cfg_buf[GTP_ADDR_LENGTH] &= 0x07; } GTP_DEBUG("SENSOR ID:%d", rd_cfg_buf[GTP_ADDR_LENGTH]); memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf[rd_cfg_buf[GTP_ADDR_LENGTH]], ts->gtp_cfg_len); #if GTP_CUSTOM_CFG config[RESOLUTION_LOC] = (u8)ts->data->gtp_max_width; config[RESOLUTION_LOC + 1] = (u8)(ts->data->gtp_max_width>>8); config[RESOLUTION_LOC + 2] = (u8)ts->data->gtp_max_height; config[RESOLUTION_LOC + 3] = (u8)(ts->data->gtp_max_height>>8); if (GTP_INT_TRIGGER == 0) /* RISING */ config[TRIGGER_LOC] &= 0xfe; else if (GTP_INT_TRIGGER == 1) /* FALLING */ config[TRIGGER_LOC] |= 0x01; #endif check_sum = 0; for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++) check_sum += config[i]; config[ts->gtp_cfg_len] = (~check_sum) + 1; #else if (ts->gtp_cfg_len == 0) ts->gtp_cfg_len = GTP_CONFIG_MAX_LENGTH; ret = gtp_i2c_read(ts->client, config, ts->gtp_cfg_len + GTP_ADDR_LENGTH); if (ret < 0) { GTP_ERROR("GTP read resolution & max_touch_num failed, " \ "use default value!"); ts->abs_x_max = ts->data->gtp_max_width; ts->abs_y_max = ts->data->gtp_max_height; ts->int_trigger_type = GTP_INT_TRIGGER; return ret; } #endif GTP_DEBUG_FUNC(); ts->abs_x_max = (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC]; ts->abs_y_max = (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2]; ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03; if ((!ts->abs_x_max) || (!ts->abs_y_max)) { GTP_ERROR("GTP resolution & max_touch_num invalid, " \ "use default value!"); ts->abs_x_max = ts->data->gtp_max_width; ts->abs_y_max = ts->data->gtp_max_height; } /* MUST delay >20ms before send cfg */ GTP_MSLEEP(20); ret = gtp_send_cfg(ts->client); if (ret < 0) { GTP_ERROR("Send config error."); return ret; } GTP_DEBUG("X_MAX = %d,Y_MAX = %d,TRIGGER = 0x%02x", ts->abs_x_max, ts->abs_y_max, ts->int_trigger_type); GTP_MSLEEP(10); return 0; }
/*@return, 0:operate successfully / > 0: the length of memory size ioctl has accessed, / error otherwise.*/ static long gt1x_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { u32 value = 0; s32 ret = 0; /*the initial value must be 0*/ u8 *data = NULL; static struct ratelimit_state ratelimit = { .lock = __RAW_SPIN_LOCK_UNLOCKED(ratelimit.lock), .interval = HZ/2, .burst = 1, .begin = 1, }; GTP_DEBUG("IOCTL CMD:%x", cmd); /*GTP_DEBUG("command:%d, length:%d, rw:%s", _IOC_NR(cmd), _IOC_SIZE(cmd), (_IOC_DIR(cmd) & _IOC_READ) ? "read" : (_IOC_DIR(cmd) & _IOC_WRITE) ? "write" : "-");*/ if (_IOC_DIR(cmd)) { s32 err = -1; s32 data_length = _IOC_SIZE(cmd); data = kzalloc(data_length, GFP_KERNEL); memset(data, 0, data_length); if (_IOC_DIR(cmd) & _IOC_WRITE) { err = copy_from_user(data, (void __user *)arg, data_length); if (err) { GTP_DEBUG("Can't access the memory."); kfree(data); return -1; } } } else { value = (u32) arg; } switch (cmd & NEGLECT_SIZE_MASK) { case IO_GET_VERSION: if ((u8 __user *) arg) { ret = copy_to_user(((u8 __user *) arg), IO_VERSION, sizeof(IO_VERSION)); if (!ret) ret = sizeof(IO_VERSION); GTP_INFO("%s", IO_VERSION); } break; case IO_IIC_READ: if (1 == gt1x_is_tpd_halt()) { if (__ratelimit(&ratelimit)) GTP_ERROR("touch is suspended."); break; } ret = io_iic_read(data, (void __user *)arg); break; case IO_IIC_WRITE: if (1 == gt1x_is_tpd_halt()) { if (__ratelimit(&ratelimit)) GTP_ERROR("touch is suspended."); break; } ret = io_iic_write(data); break; case IO_RESET_GUITAR: gt1x_reset_guitar(); break; case IO_DISABLE_IRQ: gt1x_irq_disable(); #ifdef CONFIG_GTP_ESD_PROTECT gt1x_esd_switch(SWITCH_OFF); #endif break; case IO_ENABLE_IRQ: gt1x_irq_enable(); #ifdef CONFIG_GTP_ESD_PROTECT gt1x_esd_switch(SWITCH_ON); #endif break; /*print a string to syc log messages between application and kernel.*/ case IO_PRINT: if (data) GTP_INFO("%s", (char *)data); break; #ifdef CONFIG_GTP_GESTURE_WAKEUP case GESTURE_ENABLE_TOTALLY: GTP_DEBUG("ENABLE_GESTURE_TOTALLY"); gesture_enabled = (is_all_dead(gestures_flag, sizeof(gestures_flag)) ? 0 : 1); break; case GESTURE_DISABLE_TOTALLY: GTP_DEBUG("DISABLE_GESTURE_TOTALLY"); gesture_enabled = 0; break; case GESTURE_ENABLE_PARTLY: SETBIT(gestures_flag, (u8) value); gesture_enabled = 1; GTP_DEBUG("ENABLE_GESTURE_PARTLY, gesture = 0x%02X, gesture_enabled = %d", value, gesture_enabled); break; case GESTURE_DISABLE_PARTLY: ret = QUERYBIT(gestures_flag, (u8) value); if (!ret) break; CLEARBIT(gestures_flag, (u8) value); if (is_all_dead(gestures_flag, sizeof(gestures_flag))) gesture_enabled = 0; GTP_DEBUG("DISABLE_GESTURE_PARTLY, gesture = 0x%02X, gesture_enabled = %d", value, gesture_enabled); break; case GESTURE_DATA_OBTAIN: GTP_DEBUG("OBTAIN_GESTURE_DATA"); mutex_lock(&gesture_data_mutex); if (gesture_data.data[1] > GESTURE_MAX_POINT_COUNT) gesture_data.data[1] = GESTURE_MAX_POINT_COUNT; if (gesture_data.data[3] > 80) gesture_data.data[3] = 80; ret = copy_to_user(((u8 __user *) arg), &gesture_data.data, 4 + gesture_data.data[1] * 4 + gesture_data.data[3]); mutex_unlock(&gesture_data_mutex); if (ret) { GTP_ERROR("ERROR when copy gesture data to user."); ret = ERROR_MEM; } else { ret = 4 + gesture_data.data[1] * 4 + gesture_data.data[3]; } break; case GESTURE_DATA_ERASE: GTP_DEBUG("ERASE_GESTURE_DATA"); gesture_clear_wakeup_data(); break; #endif /*CONFIG_GTP_GESTURE_WAKEUP*/ #ifdef CONFIG_GTP_HOTKNOT case HOTKNOT_LOAD_HOTKNOT: ret = hotknot_load_hotknot_subsystem(); break; case HOTKNOT_LOAD_AUTHENTICATION: if (1 == gt1x_is_tpd_halt()) { GTP_ERROR("touch is suspended."); break; } #ifdef CONFIG_GTP_ESD_PROTECT gt1x_esd_switch(SWITCH_ON); #endif ret = hotknot_load_authentication_subsystem(); break; case HOTKNOT_RECOVERY_MAIN: if (1 == gt1x_is_tpd_halt()) { GTP_ERROR("touch is suspended."); break; } ret = hotknot_recovery_main_system(); break; #ifdef CONFIG_HOTKNOT_BLOCK_RW case HOTKNOT_DEVICES_PAIRED: hotknot_paired_flag = 0; force_wake_flag = 0; block_enable = 1; ret = hotknot_block_rw(HN_DEVICE_PAIRED, (s32) value); break; case HOTKNOT_MASTER_SEND: ret = hotknot_block_rw(HN_MASTER_SEND, (s32) value); if (!ret) ret = got_hotknot_extra_state; break; case HOTKNOT_SLAVE_RECEIVE: ret = hotknot_block_rw(HN_SLAVE_RECEIVED, (s32) value); if (!ret) ret = got_hotknot_extra_state; break; case HOTKNOT_MASTER_DEPARTED: ret = hotknot_block_rw(HN_MASTER_DEPARTED, (s32) value); break; case HOTKNOT_SLAVE_DEPARTED: ret = hotknot_block_rw(HN_SLAVE_DEPARTED, (s32) value); break; case HOTKNOT_WAKEUP_BLOCK: hotknot_wakeup_block(); break; #endif /*CONFIG_HOTKNOT_BLOCK_RW*/ #endif /*CONFIG_GTP_HOTKNOT*/ default: GTP_INFO("Unknown cmd."); ret = -1; break; } if (data != NULL) kfree(data); return ret; } #ifdef CONFIG_GTP_HOTKNOT #ifdef CONFIG_COMPAT static long gt1x_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret; void __user *arg32 = NULL; GTP_DEBUG("gt1x_compat_ioctl cmd = %x, arg: 0x%lx\n", cmd, arg); arg32 = compat_ptr(arg); if (!file->f_op || !file->f_op->unlocked_ioctl) return -ENOTTY; /*GTP_DEBUG("gt1x_compat_ioctl arg: 0x%lx, arg32: 0x%p\n",arg, arg32);*/ switch (cmd & NEGLECT_SIZE_MASK) { case COMPAT_IO_GET_VERSION: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_IO_GET_VERSION\n");*/ if (arg32 == NULL) { GTP_ERROR("invalid argument."); return -EINVAL; } ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_IO_IIC_READ: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_IO_IIC_READ\n");*/ if (arg32 == NULL) { GTP_ERROR("invalid argument."); return -EINVAL; } ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_IO_IIC_WRITE: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_IO_IIC_WRITE\n");*/ if (arg32 == NULL) { GTP_ERROR("invalid argument."); return -EINVAL; } ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_IO_RESET_GUITAR: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_IO_RESET_GUITAR\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_IO_DISABLE_IRQ: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_IO_DISABLE_IRQ\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_IO_ENABLE_IRQ: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_IO_ENABLE_IRQ\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_IO_PRINT: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_IO_PRINT\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_GESTURE_ENABLE_TOTALLY: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_GESTURE_ENABLE_TOTALLY\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_GESTURE_DISABLE_TOTALLY: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_GESTURE_DISABLE_TOTALLY\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_GESTURE_ENABLE_PARTLY: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_GESTURE_ENABLE_PARTLY\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_GESTURE_DISABLE_PARTLY: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_GESTURE_DISABLE_PARTLY\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_GESTURE_DATA_OBTAIN: if (arg32 == NULL) { GTP_ERROR("invalid argument."); return -EINVAL; } /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_GESTURE_DATA_OBTAIN\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_GESTURE_DATA_ERASE: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_GESTURE_DATA_ERASE\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_HOTKNOT_LOAD_HOTKNOT: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_HOTKNOT_LOAD_HOTKNOT\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_HOTKNOT_LOAD_AUTHENTICATION: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_HOTKNOT_LOAD_AUTHENTICATION\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_HOTKNOT_RECOVERY_MAIN: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_HOTKNOT_RECOVERY_MAIN\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_HOTKNOT_DEVICES_PAIRED: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_HOTKNOT_DEVICES_PAIRED\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_HOTKNOT_MASTER_SEND: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_HOTKNOT_MASTER_SEND\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_HOTKNOT_SLAVE_RECEIVE: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_HOTKNOT_SLAVE_RECEIVE\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_HOTKNOT_MASTER_DEPARTED: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_HOTKNOT_MASTER_DEPARTED\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_HOTKNOT_SLAVE_DEPARTED: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_HOTKNOT_SLAVE_DEPARTED\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; case COMPAT_HOTKNOT_WAKEUP_BLOCK: /*GTP_DEBUG("gt1x_compat_ioctl COMPAT_HOTKNOT_WAKEUP_BLOCK\n");*/ ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32); break; default: GTP_INFO("Unknown cmd."); ret = -1; break; } return ret; }
s32 hotknot_event_handler(u8 *data) { u8 hn_pxy_state = 0; u8 hn_pxy_state_bak = 0; static u8 hn_paired_cnt; u8 hn_state_buf[10] = { 0 }; u8 finger = data[0]; u8 id = 0; if (block_enable && !hotknot_paired_flag && (finger & 0x0F)) { id = data[1]; hn_pxy_state = data[2] & 0x80; hn_pxy_state_bak = data[3] & 0x80; if ((32 == id) && (0x80 == hn_pxy_state) && (0x80 == hn_pxy_state_bak)) { #ifdef HN_DBLCFM_PAIRED if (hn_paired_cnt++ < 2) return 0; #endif GTP_DEBUG("HotKnot paired!"); if (wait_hotknot_state & HN_DEVICE_PAIRED) { GTP_DEBUG("INT wakeup HN_DEVICE_PAIRED block polling waiter"); got_hotknot_state |= HN_DEVICE_PAIRED; wake_up_interruptible(&bp_waiter); } block_enable = 0; hotknot_paired_flag = 1; return 0; } got_hotknot_state &= (~HN_DEVICE_PAIRED); hn_paired_cnt = 0; } if (hotknot_paired_flag) { s32 ret = -1; ret = gt1x_i2c_read(GTP_REG_HN_STATE, hn_state_buf, 6); if (ret < 0) { GTP_ERROR("I2C transfer error. errno:%d\n ", ret); return 0; } got_hotknot_state = 0; GTP_DEBUG("wait_hotknot_state:%x", wait_hotknot_state); GTP_DEBUG("[0x8800~0x8803]=0x%x,0x%x,0x%x,0x%x", hn_state_buf[0], hn_state_buf[1], hn_state_buf[2], hn_state_buf[3]); if (wait_hotknot_state & HN_MASTER_SEND) { if ((0x03 == hn_state_buf[0]) || (0x04 == hn_state_buf[0]) || (0x07 == hn_state_buf[0])) { GTP_DEBUG("Wakeup HN_MASTER_SEND block polling waiter"); got_hotknot_state |= HN_MASTER_SEND; got_hotknot_extra_state = hn_state_buf[0]; wake_up_interruptible(&bp_waiter); } } else if (wait_hotknot_state & HN_SLAVE_RECEIVED) { if ((0x03 == hn_state_buf[1]) || (0x04 == hn_state_buf[1]) || (0x07 == hn_state_buf[1])) { GTP_DEBUG("Wakeup HN_SLAVE_RECEIVED block polling waiter:0x%x", hn_state_buf[1]); got_hotknot_state |= HN_SLAVE_RECEIVED; got_hotknot_extra_state = hn_state_buf[1]; wake_up_interruptible(&bp_waiter); } } else if (wait_hotknot_state & HN_MASTER_DEPARTED) { if (0x07 == hn_state_buf[0]) { GTP_DEBUG("Wakeup HN_MASTER_DEPARTED block polling waiter"); got_hotknot_state |= HN_MASTER_DEPARTED; wake_up_interruptible(&bp_waiter); } } else if (wait_hotknot_state & HN_SLAVE_DEPARTED) { if (0x07 == hn_state_buf[1]) { GTP_DEBUG("Wakeup HN_SLAVE_DEPARTED block polling waiter"); got_hotknot_state |= HN_SLAVE_DEPARTED; wake_up_interruptible(&bp_waiter); } } return 0; } return -1; }
static int hotknot_release(struct inode *node, struct file *filp) { GTP_DEBUG("Hotknot is disable."); hotknot_enabled = 0; return 0; }
static int hotknot_open(struct inode *node, struct file *flip) { GTP_DEBUG("Hotknot is enable."); hotknot_enabled = 1; return 0; }
s32 gesture_event_handler(struct input_dev *dev) { u8 doze_buf[4] = { 0 }; s32 ret = -1; int len, extra_len; if (DOZE_ENABLED == gesture_doze_status) { ret = gt1x_i2c_read(GTP_REG_WAKEUP_GESTURE, doze_buf, 4); 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 (ret == 0 && doze_buf[0] != 0) { if (!QUERYBIT(gestures_flag, doze_buf[0])) { GTP_INFO("Sorry, this gesture has been disabled."); doze_buf[0] = 0x00; gt1x_i2c_write(GTP_REG_WAKEUP_GESTURE, doze_buf, 1); return 0; } mutex_lock(&gesture_data_mutex); len = doze_buf[1]; if (len > GESTURE_MAX_POINT_COUNT) { GTP_ERROR("Gesture contain too many points!(%d)", len); len = GESTURE_MAX_POINT_COUNT; } if (len > 0) { ret = gt1x_i2c_read(GTP_REG_WAKEUP_GESTURE_DETAIL, &gesture_data.data[4], len * 4); if (ret < 0) { GTP_DEBUG("Read gesture data failed."); mutex_unlock(&gesture_data_mutex); return 0; } } extra_len = doze_buf[3]; if (extra_len > 80) { GTP_ERROR("Gesture contain too many extra data!(%d)", extra_len); extra_len = 80; } if (extra_len > 0) { ret = gt1x_i2c_read(GTP_REG_WAKEUP_GESTURE + 4, &gesture_data.data[4 + len * 4], extra_len); if (ret < 0) { GTP_DEBUG("Read extra gesture data failed."); mutex_unlock(&gesture_data_mutex); return 0; } } gesture_data.data[0] = doze_buf[0]; /*gesture type*/ gesture_data.data[1] = len; /*gesture points number*/ gesture_data.data[2] = doze_buf[2]; gesture_data.data[3] = extra_len; mutex_unlock(&gesture_data_mutex); GTP_DEBUG("Gesture: 0x%02X, points: %d", doze_buf[0], doze_buf[1]); doze_buf[0] = 0; gt1x_i2c_write(GTP_REG_WAKEUP_GESTURE, doze_buf, 1); input_report_key(dev, KEY_GESTURE, 1); input_sync(dev); input_report_key(dev, KEY_GESTURE, 0); input_sync(dev); return 1; } return 0; } return -1; }