int cq_item_1_func(void* data)
{		
	int i;
	ktime_t start_time, stop_time,delta;
	long long delta_us, delta_ms;
	struct ts_cmd_node cmd;
	
	cmd.command = TS_TEST_CMD;
	cmd.cmd_param.prv_params = data;
	TS_LOG_INFO("called paras:%d\n", (int)cmd.cmd_param.prv_params);

	for(i=0; i<100; i++)
	{
		init_completion(&cq_test_sync_1);
		start_time = ktime_get();
		if (NO_ERR == put_one_cmd(&cmd)) {	
			if(wait_for_completion_timeout(&cq_test_sync_1, 5*HZ)){
				stop_time = ktime_get();
				delta = ktime_sub(stop_time, start_time);
				delta_us = (long long)ktime_to_us(delta);
				delta_ms = (long long)ktime_to_ms(delta);
				TS_LOG_INFO("CMD PROCESS ELAPSED TIME: %lldms%lldus\n", delta_ms, delta_us);
			}
			else
				TS_LOG_ERR("ts thread process TEST CMD expire 5 sec\n");
		}else			
			TS_LOG_ERR("put cmd error\n");
	}
	return 0;
}
static int test_create_debugfs(void)
{
	struct dentry *root = g_ts_data.dbg_root;
	struct dentry *dir;
	struct dentry *dent;
	int i;
	int error = -EINVAL;

	if(!root){
		TS_LOG_ERR("g_ts_data dont have dbg_root\n");
		goto out;
	}

	dir = debugfs_create_dir("test_dir", root);
	if (!dir) {
		TS_LOG_ERR("failed to create test_dir directory\n");
		goto out;
	}
	
	for(i = 0; i<ARRAY_SIZE(g_test_items); i++){
		dent = debugfs_create_u32(g_test_items[i].item_name, S_IRUGO | S_IWUSR, dir, &g_test_items[i].item_switch); 
		if (!dent) {
			TS_LOG_ERR("failed to create %s file\n", g_test_items[i].item_name);
			debugfs_remove_recursive(dir);
			break;
		}
	}

	if(i==ARRAY_SIZE(g_test_items))
		error = NO_ERR;
	
out:
	return error;
}
int synaptics_fw_configid(struct synaptics_rmi4_data *rmi4_data, u8 *buf)
{
	int rc = 0;
	unsigned char config_id[4];
	unsigned char f34_ctrl_base_addr = 0;

	TS_LOG_INFO("called\n");

	rc = synaptics_get_f34_addr(rmi4_data, &f34_ctrl_base_addr);
	if (rc < 0){
		TS_LOG_ERR("failed to scan pdt\n");
	}

	rc = rmi4_data->i2c_read(rmi4_data, f34_ctrl_base_addr, config_id, sizeof(config_id));
	if (rc < 0) {
		TS_LOG_ERR("Could not read configid\n");
		return rc;
	}

	TS_LOG_INFO("config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X,addr = 0x%02x\n",
                                config_id[0], config_id[1], config_id[2], config_id[3], f34_ctrl_base_addr);

	snprintf(buf, PAGE_SIZE, "%02x %02x %02x %02x\n",
			config_id[0],
			config_id[1],
			config_id[2],
			config_id[3]);

	TS_LOG_INFO("buf = %s\n", buf);
	return 0;
}
static int filter_illegal_glove(u8 n_finger, struct ts_fingers *in_info)
{
	u8 report_flag = 0;
	long interval_time;
	u8 new_mode;
	int x = in_info->fingers[n_finger].x;
	int y = in_info->fingers[n_finger].y;
	new_mode = in_info->fingers[n_finger].status;

	if (new_mode == TP_FINGER) { /*the new interrupt is a finger signal*/
		touch_state = FINGER_STATE;
		report_flag = 1;
	} else if ((new_mode == TP_GLOVE) || (new_mode == TP_STYLUS)) { /*the new interrupt is a glove signal.*/
		switch (touch_state) {
			case INIT_STATE:
				report_flag = 1;
				touch_state = GLOVE_STATE;
				break;

			case FINGER_STATE:
				ktime_get_ts(&curr_time[n_finger]);
				interval_time = (curr_time[n_finger].tv_sec - pre_finger_time[n_finger].tv_sec)*1000
					+ (curr_time[n_finger].tv_nsec - pre_finger_time[n_finger].tv_nsec)/1000000;
				if (interval_time > 0 && interval_time <= FINGER_REL_TIME) {
					ktime_get_ts(&pre_finger_time[n_finger]);
				} else {
					touch_state = ZERO_STATE;
				}
				break;

			case ZERO_STATE:
				if ((touch_pos_x[n_finger] == -1) && (touch_pos_y[n_finger] == -1)) {
					touch_pos_x[n_finger] = x;
					touch_pos_y[n_finger] = y;
				} else {
					if (((touch_pos_x[n_finger] - x)*(touch_pos_x[n_finger] - x)
						+ (touch_pos_y[n_finger] - y)*(touch_pos_y[n_finger] - y))
						>= (PEN_MOV_LENGTH * PEN_MOV_LENGTH)) {
						touch_state = GLOVE_STATE;
					}
				}
				break;

			case GLOVE_STATE:
				report_flag = 1;
				break;

			default:
				TS_LOG_ERR("error: touch_state = %d\n", touch_state);
				break;
		}
	}else {
		TS_LOG_ERR("error:cur_mode=%d\n", new_mode);
		report_flag = 1;
	}

	return report_flag;
}
/*
 * 0 : holster mode is off.
   1 : holster mode is on.
  -1 : get holster mode is error.
*/
int cyttsp5_get_holster_mode(struct device *dev)
{
    int rc;
    int i = 0;
    int index = 0;
    int num_read = 0;
    int length = 0;
    u8 response_buf[CY_MAX_BUF_SIZE] = {0};
    char response_str[COVER_RESPONSE_MAX_LEN] = {0};

    TS_LOG_DEBUG("Enter %s.\n", __func__);

    memset(response_buf, 0, sizeof(response_buf));

    rc = cyttsp5_send_command(dev,holster_command[GET_HOLSTER_MODE]);
    if (rc || !cyttsp5_command_status(dev)) {
        TS_LOG_ERR("%s: Send read TP holster mode command failed.\n", __func__);
        return -1;
    }

    msleep(10);

    num_read = cyttsp5_command_response(dev,response_buf);
    if (!cyttsp5_command_status(dev) || num_read < 0) {
        TS_LOG_ERR("%s: Get TP holster mode command response failed.\n", __func__);
        return -1;
    }

    for (i = 0; i < num_read; i++) {
        TS_LOG_DEBUG("%s,response_buf[%d]=0x%02X.\n", __func__,i,response_buf[i]);
        index += scnprintf(response_str + index, COVER_RESPONSE_MAX_LEN,
                           "%02X ", response_buf[i]);
    }

    TS_LOG_DEBUG("%s,response_str=%s.\n", __func__,response_str);

    //response string len.
    length = strlen(holster_response_state[GET_HOLSTER_ON_RESPONSE_ONE]);
    TS_LOG_DEBUG("%s,length = %d.\n", __func__,length);

    //holster mode on.
    for(i = GET_HOLSTER_ON_RESPONSE_ONE; i <= GET_HOLSTER_ON_RESPONSE_TWO; i++) {
        if (strncmp(holster_response_state[i], response_str, length) == 0) {
            return 1;
        }
    }

    //holster mode off or default status.
    for(i = GET_HOLSTER_OFF_RESPONSE_ONE; i <= GET_HOLSTER_DEFAULT_RESPONSE_TWO; i++) {
        if (strncmp(holster_response_state[i], response_str, length) == 0) {
            return 0;
        }
    }

    TS_LOG_ERR("%s: get touch holster mode failed.\n", __func__);
    return -1;
}
int ts_register_algo_func(struct ts_device_data *chip_data)
{
	int retval = 0;

	retval = register_algo_func(chip_data, &ts_algo_f1);	//put algo_f1 into list contained in chip_data, named algo_t1
	if (retval < 0) {
		TS_LOG_ERR("alog 1 failed, retval = %d\n", retval);
		return retval;
	}

	retval = register_algo_func(chip_data, &ts_algo_f2);	//put algo_f2 into list contained in chip_data, named algo_t2
	if (retval < 0) {
		TS_LOG_ERR("alog 2 failed, retval = %d\n", retval);
		return retval;
	}

	return retval;
}
/* Use to record configid */
int synaptics_fw_configid(struct synaptics_rmi4_data *rmi4_data)
{
    int rc = 0;
    unsigned char f34_ctrl_base_addr = 0;

    TS_LOG_INFO("synaptics_fw_configid called\n");

    rc = synaptics_get_f34_addr(rmi4_data, &f34_ctrl_base_addr);
    if (rc < 0) {
        TS_LOG_ERR("failed to scan pdt\n");
    }

    rc = rmi4_data->i2c_read(rmi4_data, f34_ctrl_base_addr, s3320_config_id, sizeof(s3320_config_id));
    if (rc < 0) {
        TS_LOG_ERR("Could not read configid\n");
        return rc;
    }

    TS_LOG_INFO("config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X,addr = 0x%02x\n",
                s3320_config_id[0], s3320_config_id[1], s3320_config_id[2], s3320_config_id[3], f34_ctrl_base_addr);

    return 0;
}
static int synaptics_get_f34_addr(struct synaptics_rmi4_data *rmi4_data, unsigned char*f34_address)
{
    int retval;
    unsigned short addr;
    struct synaptics_rmi4_fn_desc rmi_fd;

    for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE)
    {
        retval = rmi4_data->i2c_read(rmi4_data, addr, (unsigned char *)&rmi_fd, sizeof(rmi_fd));
        if (retval < 0) {
            TS_LOG_ERR("Failed to read map register\n");
            return retval;
        }

        if (SYNAPTICS_RMI4_F34 == rmi_fd.fn_number) {
            TS_LOG_INFO("Found F%02x\n", rmi_fd.fn_number);
            *f34_address = rmi_fd.ctrl_base_addr;
            return NO_ERR;
        }
    }
    TS_LOG_ERR("Failed to get f34 addr\n");
    return -EINVAL;
}
int input_item_1_func(void* data)
{
	struct ts_cmd_node cmd;
	
	cmd.command = TS_TEST_CMD;
	cmd.cmd_param.prv_params = data;
	TS_LOG_INFO("called paras:%d\n", (int)cmd.cmd_param.prv_params);
	
	if (NO_ERR != put_one_cmd(&cmd)) {
		TS_LOG_ERR("put cmd failed\n");
	}
	
	return 0;
}
int cq_item_2_func(void* data)
{
	int i;
	struct ts_cmd_node cmd;
	
	cmd.command = TS_TEST_CMD;
	cmd.cmd_param.prv_params = data;
	TS_LOG_INFO("called paras:%d\n", (int)cmd.cmd_param.prv_params);

	for (i=0; i<100; i++)
	{
		init_completion(&cq_test_sync_1);
		if (NO_ERR == put_one_cmd(&cmd)) {	
			if(wait_for_completion_timeout(&cq_test_sync_1, 5*HZ)){
				TS_LOG_INFO("CMD PROCESS %d FINISH - cpu id:%d\n", i, smp_processor_id());
			}
			else
				TS_LOG_ERR("ts thread process TEST CMD expire 5 sec\n");
		}else			
			TS_LOG_ERR("put cmd error\n");
	}
	return 0;
}
static int fwu_read_f01_device_status(struct f01_device_status *status)
{
    int retval;

    retval = fwu->fn_ptr->read(fwu->rmi4_data,
                               fwu->f01_fd.data_base_addr,
                               status->data,
                               sizeof(status->data));
    if (retval < 0) {
        TS_LOG_ERR("Failed to read F01 device status\n");
        return retval;
    }

    return 0;
}
static int __init ts_test_init(void)
{
	struct task_struct *test_task;

	TS_LOG_INFO("ts_test_init called here\n");
	return 0;

	test_task = kthread_create_on_node(ts_test_thread, NULL,  cpu_to_node(2), "ts_test_thread");
	if (IS_ERR(test_task))
		TS_LOG_ERR("create ts_thread failed\n");
	else
		wake_up_process(test_task);

	return 0;
}
struct kobject* tp_get_virtual_key_obj(char *name)
{
    if( NULL == virtual_key_kobject_ts ) {
        virtual_key_kobject_ts = kobject_create_and_add(name, NULL);
        if (!virtual_key_kobject_ts) {
            TS_LOG_ERR("%s: create virtual_key kobjetct error!\n", __func__);
            return NULL;
        } else {
            TS_LOG_DEBUG("%s: create virtual_key successful!\n", __func__);
        }
    } else {
        TS_LOG_DEBUG("%s: virtual_key already exist!\n", __func__);
    }

    return virtual_key_kobject_ts;
}
int test_dbg_cmd_test(struct ts_cmd_node *in_cmd,struct ts_cmd_node *out_cmd)
{
	enum ts_test_item_enum test_item = (enum ts_test_item_enum)in_cmd->cmd_param.prv_params;
	int error = NO_ERR;
	int rec_v, cal_v;
	struct ts_fingers test_pos;
	
	switch(test_item){
		case TEST_CMDQ_ITEM_1:
			complete(&cq_test_sync_1);
			break;
		case TEST_CMDQ_ITEM_2:
			TS_LOG_INFO("cpu id:%d\n", smp_processor_id());
			complete(&cq_test_sync_1);
			break;
		case TEST_CMDQ_ITEM_3:
			if(!cq_test_buff_index){
				wait_for_completion(&cq_test_sync_1); //wait for send finish
				smp_mb();
			}
			cal_v = cq_test_buff[cq_test_buff_index];
			rec_v = in_cmd->cmd_param.pub_params.algo_param.algo_order;
			TS_LOG_INFO("index :%d, rec data:%d, cal data:%d, result: %s\n", 
					cq_test_buff_index, rec_v, cal_v, (rec_v==cal_v)?"pass":"******");
			cq_test_buff_index++;
			if(cq_test_buff[cq_test_buff_index] == -1){//whether reach the end of buffer
				TS_LOG_INFO("REACH TEST BUFF END, index :%d\n", cq_test_buff_index);
				cq_test_buff_index = 0;
				complete(&cq_test_sync_2);
			}
			break;
		case TEST_INPUT_ITEM_1:
			test_pos.fingers[0].x = 0;
			test_pos.fingers[0].y = 0;
			test_pos.fingers[0].area = 0;
			test_pos.fingers[0].pressure = 0;
			test_pos.fingers[0].status= 0;
			memcpy(&out_cmd->cmd_param.pub_params.report_info, &test_pos, sizeof(struct ts_fingers));	
			out_cmd->command = TS_REPORT_INPUT;
			break;
		default:
			TS_LOG_ERR("unsupport item :%d \n", test_item);
			break;
	}
	TS_LOG_INFO("test item :%d result :%d\n", test_item, error);
	return error;
}
static int fwu_read_f34_flash_status(void)
{
    int retval;
    unsigned char status;
    unsigned char command;

    retval = fwu->fn_ptr->read(fwu->rmi4_data,
                               fwu->f34_fd.data_base_addr + fwu->flash_status_off,
                               &status,
                               sizeof(status));
    if (retval < 0) {
        TS_LOG_ERR("Failed to read flash status\n");
        return retval;
    }

    fwu->program_enabled = status >> 7;

    if (fwu->bl_version == V5)
        fwu->flash_status = (status >> 4) & MASK_3BIT;
    else if (fwu->bl_version == V6)
static int ts_test_thread(void *p)
{
	int i = 0;
	int ret;
	
	while(atomic_read(&g_ts_data.state) != TS_WORK && i < WAIT_MAX_COUNT){
		TS_LOG_INFO("touchscreen module init not finish\n");
		msleep(1000);
		i++;
	}

	TS_LOG_INFO("touchscreen test init\n");

	if(test_create_debugfs()){
		TS_LOG_ERR("touchscreen test create debugfs failed\n");
		goto out;
	}

	TS_LOG_INFO("touchscreen test start polling\n");

	wake_lock_init(&ts_test_wake_lock, WAKE_LOCK_IDLE, "ts_test");
	
repeat:
	msleep(1000);
	for(i = 0, ret = -99; i<ARRAY_SIZE(g_test_items); i++){
		if(!g_test_items[i].item_switch)
			continue;
		wake_lock(&ts_test_wake_lock);
		TS_LOG_INFO("touchscreen test :%s begin\n", g_test_items[i].item_name);
		if(g_test_items[i].test_func)
			ret = g_test_items[i].test_func(g_test_items[i].item_data);
		TS_LOG_INFO("touchscreen test :%s end, ret:%d\n",  g_test_items[i].item_name, ret);
		g_test_items[i].item_switch = 0;
		wake_unlock(&ts_test_wake_lock);
	}	
	goto repeat;
	
out:	
	return 0;
}
int cq_item_3_func(void* data)
{
	int i;
	struct ts_cmd_node cmd;
	
	cmd.command = TS_TEST_CMD;
	cmd.cmd_param.prv_params = data;
	TS_LOG_INFO("called paras:%d\n", (int)cmd.cmd_param.prv_params);
	memset(cq_test_buff, -1, sizeof(cq_test_buff));
	init_completion(&cq_test_sync_1);
	init_completion(&cq_test_sync_2);

	for(i=0; i<TS_CMD_QUEUE_SIZE+5; i++){
		cmd.cmd_param.pub_params.algo_param.algo_order = i;
		cq_test_buff[i] = i;
		if(put_one_cmd(&cmd)){
			TS_LOG_INFO("SEND COMPLETE i:%d\n", i);
			if(!i)
				goto out;//unput any cmd, just break;
			cq_test_buff[i] = -1;
			smp_mb();
			complete(&cq_test_sync_1);
			if(try_wait_for_completion(&cq_test_sync_2) ||
				wait_for_completion_timeout(&cq_test_sync_2, 10*HZ))
			{
				TS_LOG_INFO("CMD PROCESS FINISH\n");
			}
			else
				TS_LOG_ERR("ts thread process TEST CMD expire 10 sec\n");
			goto out;//finish 1 test break form internal loop
		}
	}
	
out:
	return 0;
}
int cyttsp5_set_holster_mode(struct device *dev,int holster_switch)
{
    u8 response_buf[CY_MAX_BUF_SIZE] = {0};
    char response_str[COVER_RESPONSE_MAX_LEN] = {0};
    int i =0;
    int num_read = 0;
    int index = 0;
    int rc = -1;
    int flag = 0;
    int length = 0;

    TS_LOG_DEBUG("Enter %s,holster_switch = %d.\n", __func__,holster_switch);

    memset(response_buf, 0, sizeof(response_buf));

    flag = cyttsp5_get_holster_mode(dev);
    if(flag < 0) {
        TS_LOG_ERR("%s,get Touch holster mode failed.\n",__func__);
        return -1;
    }

    if (holster_switch == flag) {
        TS_LOG_INFO("%s,Touch is already in %s mode.\n",__func__,(flag == 1) ? "holster ON" : "holster OFF");
        return 0;
    }

    TS_LOG_DEBUG("%s,Begin to switch holster mode.\n", __func__);

    if (holster_switch) {
        rc = cyttsp5_send_command(dev,holster_command[SET_HOLSTER_ON]);
        if (rc || !cyttsp5_command_status(dev)) {
            TS_LOG_ERR("%s: Send read TP holster mode command failed!\n", __func__);
            goto exit;
        }
    } else {
        rc = cyttsp5_send_command(dev,holster_command[SET_HOLSTER_OFF]);
        if (rc || !cyttsp5_command_status(dev)) {
            TS_LOG_ERR("%s: Send read TP holster mode command failed!\n", __func__);
            goto exit;
        }

    }

    msleep(50);

    num_read = cyttsp5_command_response(dev,response_buf);
    if (!cyttsp5_command_status(dev) || num_read < 0) {
        TS_LOG_ERR("%s: Get command response failed\n", __func__);
        goto exit;
    }

    for (i = 0; i < num_read; i++) {
        index += scnprintf(response_str + index, COVER_RESPONSE_MAX_LEN,
                           "%02X ", response_buf[i]);
    }

    TS_LOG_DEBUG("%s,response_str=%s.\n",__func__,response_str);

    length = strlen(holster_response_state[SET_HOLSTER_SUCCESSFUL_ONE]);
    for(i = SET_HOLSTER_SUCCESSFUL_ONE; i <= SET_HOLSTER_SUCCESSFUL_TWO; i++) {
        if (strncmp(holster_response_state[i], response_str, length) == 0) {
            TS_LOG_INFO("%s,Set TP holster mode successful!\n",__func__);
            return 0;
        }
    }

    rc = -1;
exit:
    TS_LOG_ERR("%s,Set TP holster mode failed.\n",__func__);
    return rc;
}
static int fwu_read_f34_queries(void)
{
    int retval;
    unsigned char count;
    unsigned char buf[10];

    retval = fwu->fn_ptr->read(fwu->rmi4_data,
                               fwu->f34_fd.query_base_addr + BOOTLOADER_ID_OFFSET,
                               fwu->bootloader_id,
                               sizeof(fwu->bootloader_id));
    if (retval < 0) {
        TS_LOG_ERR("Failed to read bootloader ID\n");
        return retval;
    }

    TS_LOG_INFO("bootloader_id[1] = %c", fwu->bootloader_id[1]);

    if (fwu->bootloader_id[1] == '5') {
        fwu->bl_version = V5;
    } else if (fwu->bootloader_id[1] == '6') {
        fwu->bl_version = V6;
    } else {
        TS_LOG_ERR("Unrecognized bootloader version\n");
        return -EINVAL;
    }

    if (fwu->bl_version == V5) {
        fwu->properties_off = V5_PROPERTIES_OFFSET;
        fwu->blk_size_off = V5_BLOCK_SIZE_OFFSET;
        fwu->blk_count_off = V5_BLOCK_COUNT_OFFSET;
        fwu->blk_data_off = V5_BLOCK_DATA_OFFSET;
    } else if (fwu->bl_version == V6) {
        fwu->properties_off = V6_PROPERTIES_OFFSET;
        fwu->blk_size_off = V6_BLOCK_SIZE_OFFSET;
        fwu->blk_count_off = V6_BLOCK_COUNT_OFFSET;
        fwu->blk_data_off = V6_BLOCK_DATA_OFFSET;
    }

    retval = fwu->fn_ptr->read(fwu->rmi4_data,
                               fwu->f34_fd.query_base_addr + fwu->properties_off,
                               &fwu->flash_properties,
                               sizeof(fwu->flash_properties));
    if (retval < 0) {
        TS_LOG_ERR("Failed to read flash properties\n");
        return retval;
    }

    count = 4;

    if (fwu->flash_properties & HAS_PERM_CONFIG) {
        fwu->has_perm_config = 1;
        count += 2;
    }

    if (fwu->flash_properties & HAS_BL_CONFIG) {
        fwu->has_bl_config = 1;
        count += 2;
    }

    if (fwu->flash_properties & HAS_DISP_CONFIG) {
        fwu->has_disp_config = 1;
        count += 2;
    }

    retval = fwu->fn_ptr->read(fwu->rmi4_data,
                               fwu->f34_fd.query_base_addr + fwu->blk_size_off,
                               buf,
                               2);
    if (retval < 0) {
        TS_LOG_ERR("Failed to read block size info\n");
        return retval;
    }

    batohs(&fwu->block_size, &(buf[0]));

    if (fwu->bl_version == V5) {
        fwu->flash_cmd_off = fwu->blk_data_off + fwu->block_size;
        fwu->flash_status_off = fwu->flash_cmd_off;
    } else if (fwu->bl_version == V6) {
        fwu->flash_cmd_off = V6_FLASH_COMMAND_OFFSET;
        fwu->flash_status_off = V6_FLASH_STATUS_OFFSET;
    }

    retval = fwu->fn_ptr->read(fwu->rmi4_data,
                               fwu->f34_fd.query_base_addr + fwu->blk_count_off,
                               buf,
                               count);
    if (retval < 0) {
        TS_LOG_ERR("Failed to read block count info\n");
        return retval;
    }

    batohs(&fwu->fw_block_count, &(buf[0]));
    batohs(&fwu->config_block_count, &(buf[2]));

    count = 4;

    if (fwu->has_perm_config) {
        batohs(&fwu->perm_config_block_count, &(buf[count]));
        count += 2;
    }

    if (fwu->has_bl_config) {
        batohs(&fwu->bl_config_block_count, &(buf[count]));
        count += 2;
    }

    if (fwu->has_disp_config)
        batohs(&fwu->disp_config_block_count, &(buf[count]));

    return 0;
}