/******************************************************* 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) { 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) { // 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 { 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)); return CMD_HEAD_LENGTH; } else if (9 == cmd_head.wr) //enable irq! { // gtp_irq_enable(i2c_get_clientdata(gt_client)); 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."); gtp_rawdiff_mode = true; } else { 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: Goodix tool write function. Input: standard proc write function param. Output: Return write length. ********************************************************/ static 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); if(gtp_resetting == 1) { //GTP_ERROR("[Write]tpd_halt =1 fail!"); return FAIL; } 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); 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 { 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! { mt_eint_mask(CUST_EINT_TOUCH_PANEL_NUM); #if GTP_ESD_PROTECT gtp_esd_switch(i2c_client_point, SWITCH_OFF); #endif return CMD_HEAD_LENGTH; } else if (9 == cmd_head.wr) //enable irq! { mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); #if GTP_ESD_PROTECT gtp_esd_switch(i2c_client_point, SWITCH_ON); #endif return CMD_HEAD_LENGTH; } else if (17 == cmd_head.wr) { 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."); gtp_rawdiff_mode = true; } else { 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); GTP_DEBUG("update firmware, filename: %s", cmd_head.data); if (FAIL == gup_update_proc((void *)cmd_head.data)) { return FAIL; } } #endif else if (19 == cmd_head.wr) //load subsystem { ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], cmd_head.data_len); if(0 == cmd_head.data[0]) { if (FAIL == gup_load_calibration1()) { return FAIL; } } else if(1 == cmd_head.data[0]) { if (FAIL == gup_load_calibration2()) { return FAIL; } } else if(2 == cmd_head.data[0]) { if (FAIL == gup_recovery_calibration0()) { return FAIL; } } else if(3 == cmd_head.data[0]) { if (FAIL == gup_load_calibration0(NULL)) { return FAIL; } } } #if HOTKNOT_BLOCK_RW else if (21 == cmd_head.wr) { u16 wait_hotknot_timeout = 0; u8 rqst_hotknot_state; 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."); } rqst_hotknot_state = cmd_head.data[GTP_ADDR_LENGTH]; wait_hotknot_state |= rqst_hotknot_state; wait_hotknot_timeout = (cmd_head.data[GTP_ADDR_LENGTH + 1]<<8) + cmd_head.data[GTP_ADDR_LENGTH + 2]; GTP_DEBUG("Goodix tool received wait polling state:0x%x,timeout:%d, all wait state:0x%x", rqst_hotknot_state, wait_hotknot_timeout, wait_hotknot_state); got_hotknot_state &= (~rqst_hotknot_state); //got_hotknot_extra_state = 0; switch(rqst_hotknot_state) { set_current_state(TASK_INTERRUPTIBLE); case HN_DEVICE_PAIRED: hotknot_paired_flag = 0; wait_event_interruptible(bp_waiter, force_wake_flag || rqst_hotknot_state == (got_hotknot_state&rqst_hotknot_state)); wait_hotknot_state &= (~rqst_hotknot_state); if(rqst_hotknot_state != (got_hotknot_state&rqst_hotknot_state)) { GTP_ERROR("Wait 0x%x block polling waiter failed.", rqst_hotknot_state); force_wake_flag = 0; return FAIL; } break; case HN_MASTER_SEND: case HN_SLAVE_RECEIVED: wait_event_interruptible_timeout(bp_waiter, force_wake_flag || rqst_hotknot_state == (got_hotknot_state&rqst_hotknot_state), wait_hotknot_timeout); wait_hotknot_state &= (~rqst_hotknot_state); if(rqst_hotknot_state == (got_hotknot_state&rqst_hotknot_state)) { return got_hotknot_extra_state; } else { GTP_ERROR("Wait 0x%x block polling waiter timeout.", rqst_hotknot_state); force_wake_flag = 0; return FAIL; } break; case HN_MASTER_DEPARTED: case HN_SLAVE_DEPARTED: wait_event_interruptible_timeout(bp_waiter, force_wake_flag || rqst_hotknot_state == (got_hotknot_state&rqst_hotknot_state), wait_hotknot_timeout); wait_hotknot_state &= (~rqst_hotknot_state); if(rqst_hotknot_state != (got_hotknot_state&rqst_hotknot_state)) { GTP_ERROR("Wait 0x%x block polling waitor timeout.", rqst_hotknot_state); force_wake_flag = 0; return FAIL; } break; default: GTP_ERROR("Invalid rqst_hotknot_state in goodix_tool."); break; } force_wake_flag = 0; } else if(23 == cmd_head.wr) { GTP_DEBUG("Manual wakeup all block polling waiter!"); got_hotknot_state = 0; wait_hotknot_state = 0; force_wake_flag = 1; hotknot_paired_flag = 0; wake_up_interruptible(&bp_waiter); } #endif return CMD_HEAD_LENGTH; }
static int goodix_tool_write(struct file *filp, const char __user *buff, unsigned long len, void *data) { int 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.", (int)cmd_head.circle); GTP_DEBUG("times :%d.", (int)cmd_head.times); GTP_DEBUG("retry :%d.", (int)cmd_head.retry); GTP_DEBUG("delay :%d.", (int)cmd_head.delay); GTP_DEBUG("data len:%d.", (int)cmd_head.data_len); GTP_DEBUG("addr len:%d.", (int)cmd_head.addr_len); GTP_DEBUG("addr:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]); GTP_DEBUG("len:%d.", (int)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 (comfirm() < 0) { GTP_ERROR("[WRITE]Comfirm fail!"); return -1; } } 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 -1; } 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 (gup_enter_update_mode(gt_client) < 0) return -1; } 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 (gup_update_proc((void*)cmd_head.data) < 0) return -1; } #endif return CMD_HEAD_LENGTH; }
/******************************************************* 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) { u64 ret = 0; GTP_DEBUG_FUNC(); GTP_DEBUG_ARRAY((u8 *) buff, len); if(len < CMD_HEAD_LENGTH){ GTP_ERROR("copy_from_user out of range, failed."); return -1; } 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) { if((cmd_head.data == NULL) || (cmd_head.data_len > (DATA_LENGTH - GTP_ADDR_LENGTH)) || (cmd_head.data_len > (len - CMD_HEAD_LENGTH)) ) { GTP_ERROR("copy_from_user data out of range."); return -1; } 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."); } if((cmd_head.addr_len > sizeof(cmd_head.addr))) { GTP_ERROR("copy_from_user data out of range."); return -1; } 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 */ { if((cmd_head.data == NULL) || (cmd_head.data_len > sizeof(IC_TYPE[16])) || (cmd_head.data_len > (len - CMD_HEAD_LENGTH)) ) { GTP_ERROR("copy_from_user data out of range."); return -1; } 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! */ { mt_eint_mask(CUST_EINT_TOUCH_PANEL_NUM); #if GTP_ESD_PROTECT gtp_esd_switch(i2c_client_point, SWITCH_OFF); #endif return CMD_HEAD_LENGTH; } else if (9 == cmd_head.wr) /* enable irq! */ { mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); #if GTP_ESD_PROTECT gtp_esd_switch(i2c_client_point, SWITCH_ON); #endif return CMD_HEAD_LENGTH; } else if (17 == cmd_head.wr) { if((cmd_head.data == NULL) || (cmd_head.data_len > (DATA_LENGTH - GTP_ADDR_LENGTH)) || (cmd_head.data_len > (len - CMD_HEAD_LENGTH)) ) { GTP_ERROR("copy_from_user data out of range."); return -1; } 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."); gtp_rawdiff_mode = true; } else { 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); if((cmd_head.data == NULL) || (cmd_head.data_len > DATA_LENGTH) || (cmd_head.data_len > (len - CMD_HEAD_LENGTH)) ) { GTP_ERROR("copy_from_user data out of range."); return -1; } copy_from_user(cmd_head.data, &buff[CMD_HEAD_LENGTH], cmd_head.data_len); GTP_DEBUG("update firmware, filename: %s", cmd_head.data); if (FAIL == gup_update_proc((void *)cmd_head.data)) { return FAIL; } } #endif return CMD_HEAD_LENGTH; }
//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; }