Example #1
0
bool flash_cmd(struct wacom_i2c *wac_i2c)
{
    int rv, len;
    u8 buf[10];

    len = 0;
    buf[len++] = 4;
    buf[len++] = 0;
    buf[len++] = 0x32;
    buf[len++] = CMD_SET_FEATURE;

    rv = wacom_i2c_send(wac_i2c,
                        buf, len, true);
    if (rv < 0)
        return false;

    len = 0;
    buf[len++] = 5;
    buf[len++] = 0;
    buf[len++] = 4;
    buf[len++] = 0;
    buf[len++] = 2;
    buf[len++] = 2;
    rv = wacom_i2c_send(wac_i2c,
                        buf, len, true);
    if (rv < 0)
        return false;

    return true;
}
int flash_query(struct wacom_i2c *wac_i2c)
{
	u8 command[CMD_SIZE];
	u8 response[RSP_SIZE];
	int ret, ECH;
	int len = 0;

	command[len++] = 4;	/* Command Register-LSB */
	command[len++] = 0;	/* Command Register-MSB */
	command[len++] = 0x37;	/* Command-LSB, ReportType:Feature(11) ReportID:7 */
	command[len++] = CMD_SET_FEATURE;	/* Command-MSB, SET_REPORT */
	command[len++] = 5;	/* Data Register-LSB */
	command[len++] = 0;	/* Data-Register-MSB */
	command[len++] = 5;	/* Length Field-LSB */
	command[len++] = 0;	/* Length Field-MSB */
	command[len++] = BOOT_CMD_REPORT_ID;	/* Report:ReportID */
	command[len++] = BOOT_QUERY;	/* Report:Boot Query command */
	command[len++] = ECH = 7;	/* Report:echo */

	ret = wacom_i2c_send(wac_i2c, command, len, WACOM_I2C_MODE_BOOT);
	if (ret < 0) {
		printk(KERN_DEBUG"epen:%s 2 ret:%d \n", __func__, ret);
		return -EXIT_FAIL_SEND_QUERY_COMMAND;
	}

	len = 0;
	command[len++] = 4;	/* Command Register-LSB */
	command[len++] = 0;	/* Command Register-MSB */
	command[len++] = 0x38;	/* Command-LSB, ReportType:Feature(11) ReportID:8 */
	command[len++] = CMD_GET_FEATURE;	/* Command-MSB, GET_REPORT */
	command[len++] = 5;	/* Data Register-LSB */
	command[len++] = 0;	/* Data Register-MSB */

	ret = wacom_i2c_send(wac_i2c, command, len, WACOM_I2C_MODE_BOOT);
	if (ret < 0) {
		printk(KERN_DEBUG"epen:%s 2 ret:%d \n", __func__, ret);
		return -EXIT_FAIL_SEND_QUERY_COMMAND;
	}

	msleep(10);

	ret = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
			     WACOM_I2C_MODE_BOOT);
	if (ret < 0) {
		printk(KERN_DEBUG"epen:%s 5 ret:%d \n", __func__, ret);
		return -EXIT_FAIL_SEND_QUERY_COMMAND;
	}

	if ((response[3] != QUERY_CMD) || (response[4] != ECH)) {
		printk(KERN_DEBUG"epen:%s res3:%x res4:%x \n", __func__, response[3],
		       response[4]);
		return -EXIT_FAIL_SEND_QUERY_COMMAND;
	}
	if (response[5] != QUERY_RSP) {
		printk(KERN_DEBUG"epen:%s res5:%x \n", __func__, response[5]);
		return -EXIT_FAIL_SEND_QUERY_COMMAND;
	}

	return 0;
}
static void wacom_open_test(struct wacom_i2c *wac_i2c)
{
	u8 cmd = 0;
	u8 buf[2] = {0,};
	int ret = 0, cnt = 30;

	cmd = WACOM_I2C_STOP;
	ret = wacom_i2c_send(wac_i2c, &cmd, 1, false);
	if (ret <= 0) {
		printk(KERN_ERR "[E-PEN] failed to send stop command\n");
		return ;
	}

	cmd = WACOM_I2C_GRID_CHECK;
	ret = wacom_i2c_send(wac_i2c, &cmd, 1, false);
	if (ret <= 0) {
		printk(KERN_ERR "[E-PEN] failed to send stop command\n");
		goto grid_check_error;
	}

	cmd = WACOM_STATUS;
	do {
		msleep(50);
		if (1 == wacom_i2c_send(wac_i2c, &cmd, 1, false)) {
			if (2 == wacom_i2c_recv(wac_i2c,
						buf, 2, false)) {
				switch (buf[0]) {
				/*
				*	status value
				*	0 : data is not ready
				*	1 : PASS
				*	2 : Fail (coil function error)
				*	3 : Fail (All coil function error)
				*/
				case 1:
				case 2:
				case 3:
					cnt = 0;
					break;

				default:
					break;
				}
			}
		}
	} while (cnt--);

	wac_i2c->connection_check = (1 == buf[0]);
	printk(KERN_DEBUG
	       "[E-PEN] epen_connection : %s %d\n",
	       (1 == buf[0]) ? "Pass" : "Fail", buf[1]);

grid_check_error:
	cmd = WACOM_I2C_STOP;
	wacom_i2c_send(wac_i2c, &cmd, 1, false);

	cmd = WACOM_I2C_START;
	wacom_i2c_send(wac_i2c, &cmd, 1, false);

}
static bool flash_blver(struct wacom_i2c *wac_i2c, int *blver)
{
	u8 command[CMD_SIZE];
	u8 response[RSP_SIZE];
	int ret, ECH;
	int len = 0;

	command[len++] = 4;	/* Command Register-LSB */
	command[len++] = 0;	/* Command Register-MSB */
	command[len++] = 0x37;	/* Command-LSB, ReportType:Feature(11) ReportID:7 */
	command[len++] = CMD_SET_FEATURE;	/* Command-MSB, SET_REPORT */
	command[len++] = 5;	/* Data Register-LSB */
	command[len++] = 0;	/* Data-Register-MSB */
	command[len++] = 5;	/* Length Field-LSB */
	command[len++] = 0;	/* Length Field-MSB */
	command[len++] = BOOT_CMD_REPORT_ID;	/* Report:ReportID */
	command[len++] = BOOT_BLVER;	/* Report:Boot Version command */
	command[len++] = ECH = 7;	/* Report:echo */

	ret = wacom_i2c_send(wac_i2c, command, len, WACOM_I2C_MODE_BOOT);
	if (ret < 0) {
		printk(KERN_DEBUG"epen:%s 2 ret:%d \n", __func__, ret);
		return false;
	}

	len = 0;
	command[len++] = 4;	/* Command Register-LSB */
	command[len++] = 0;	/* Command Register-MSB */
	command[len++] = 0x38;	/* Command-LSB, ReportType:Feature(11) ReportID:8 */
	command[len++] = CMD_GET_FEATURE;	/* Command-MSB, GET_REPORT */
	command[len++] = 5;	/* Data Register-LSB */
	command[len++] = 0;	/* Data Register-MSB */

	ret = wacom_i2c_send(wac_i2c, command, len, WACOM_I2C_MODE_BOOT);
	if (ret < 0) {
		printk(KERN_DEBUG"epen:%s 4 ret:%d \n", __func__, ret);
		return false;
	}

	msleep(10);

	ret =
	    wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
			   WACOM_I2C_MODE_BOOT);
	if (ret < 0) {
		printk(KERN_DEBUG"epen:%s 5 ret:%d \n", __func__, ret);
		return false;
	}

	if ((response[3] != BOOT_CMD) || (response[4] != ECH)) {
		printk(KERN_DEBUG"epen:%s res[3]:%x res[4]:%x \n", __func__, response[3],
		       response[4]);
		return false;
	}

	*blver = (int)response[5];

	return true;
}
Example #5
0
int wacom_i2c_flash_cmd(struct wacom_i2c *wac_i2c)
{
    int ret, len;
    u8 buf[8];

    pr_info("wacom: %s\n", __func__);

    buf[0] = 0x0d;
    buf[1] = FLASH_START0;
    buf[2] = FLASH_START1;
    buf[3] = FLASH_START2;
    buf[4] = FLASH_START3;
    buf[5] = FLASH_START4;
    buf[6] = FLASH_START5;
    buf[7] = 0x0d;

    len = 8;
    ret = wacom_i2c_send(wac_i2c, buf, len, true);
    if (ret < 0) {
        pr_err(
            "wacom: sending flash command failed 2\n");
        return false;
    }
    msleep(270);

    return 0;
}
int wacom_i2c_test(struct wacom_i2c *wac_i2c)
{
	int ret, i;
	char buf, test[10];
	buf = COM_QUERY;

	ret = wacom_i2c_send(wac_i2c, &buf, sizeof(buf), false);
	if (ret > 0)
		dev_info(&wac_i2c->client->dev,
			 "%s: buf:%d, sent:%d\n",
			 __func__, buf, ret);
	else {
		dev_err(&wac_i2c->client->dev,
			 "%s: Digitizer is not active\n",
			 __func__);
		return -1;
	}

	ret = wacom_i2c_recv(wac_i2c, test, sizeof(test), false);
	if (ret >= 0) {
		for (i = 0; i < 8; i++)
		dev_info(&wac_i2c->client->dev,
			 "%s: %d\n", __func__, test[i]);
	} else {
		dev_err(&wac_i2c->client->dev,
			 "%s: Digitizer does not reply\n",
			 __func__);
		return -1;
	}

	return 0;
}
static bool flash_end(struct wacom_i2c *wac_i2c)
{
	u8 command[CMD_SIZE];
	int ret, ECH;
	int len = 0;

	command[len++] = 4;
	command[len++] = 0;
	command[len++] = 0x37;
	command[len++] = CMD_SET_FEATURE;
	command[len++] = 5;
	command[len++] = 0;
	command[len++] = 5;
	command[len++] = 0;
	command[len++] = BOOT_CMD_REPORT_ID;
	command[len++] = BOOT_EXIT;
	command[len++] = ECH = 7;

	ret = wacom_i2c_send(wac_i2c, command, len, WACOM_I2C_MODE_BOOT);
	if (ret < 0) {
		printk(KERN_DEBUG"epen:%s 2 ret:%d \n", __func__, ret);
		return false;
	}
	msleep(200);

	return true;
}
int wacom_i2c_test(struct wacom_i2c *wac_i2c)
{
	int ret, i;
	char buf, test[10];
	buf = COM_QUERY;

	ret = wacom_i2c_send(wac_i2c, &buf, sizeof(buf), false);
	if (ret > 0)
		printk(KERN_INFO "[E-PEN] buf:%d, sent:%d\n", buf, ret);
	else {
		printk(KERN_ERR "[E-PEN] Digitizer is not active\n");
		return -1;
	}

	ret = wacom_i2c_recv(wac_i2c, test, sizeof(test), false);
	if (ret >= 0) {
		for (i = 0; i < 8; i++)
			printk(KERN_INFO "[E-PEN] %d\n", test[i]);
	} else {
		printk(KERN_ERR "[E-PEN] Digitizer does not reply\n");
		return -1;
	}

	return 0;
}
int wacom_checksum(struct wacom_i2c *wac_i2c)
{
	int ret = 0, retry = 10;
	int i = 0;
	u8 buf[5] = {0, };

	buf[0] = COM_CHECKSUM;

	while (retry--) {
		ret = wacom_i2c_send(wac_i2c, &buf[0], 1, false);
		if (ret < 0) {
			printk(KERN_DEBUG
			       "[E-PEN] i2c fail, retry, %d\n",
			       __LINE__);
			continue;
		}

		msleep(200);
		ret = wacom_i2c_recv(wac_i2c, buf, 5, false);
		if (ret < 0) {
			printk(KERN_DEBUG
			       "[E-PEN] i2c fail, retry, %d\n",
			       __LINE__);
			continue;
		} else if (buf[0] == 0x1f)
			break;
		printk(KERN_DEBUG "[E-PEN] checksum retry\n");
	}

	if (ret >= 0) {
		printk(KERN_DEBUG
		       "[E-PEN] received checksum %x, %x, %x, %x, %x\n",
		       buf[0], buf[1], buf[2], buf[3], buf[4]);
	}

	for (i = 0; i < 5; ++i) {
		if (buf[i] != Firmware_checksum[i]) {
			printk(KERN_DEBUG
			       "[E-PEN] checksum fail %dth %x %x\n", i,
			       buf[i], Firmware_checksum[i]);
			break;
		}
	}

	wac_i2c->checksum_result = (5 == i);

#ifdef WACOM_CONNECTION_CHECK
	if (!wac_i2c->connection_check)
		wacom_open_test(wac_i2c);
#endif

	return ret;
}
int wacom_checksum(struct wacom_i2c *wac_i2c)
{
	int ret = 0, retry = 10;
	int i = 0;
	u8 buf[5] = {0, };

	buf[0] = COM_CHECKSUM;

	while (retry--) {
		ret = wacom_i2c_send(wac_i2c, &buf[0], 1, false);
		if (ret < 0) {
			dev_err(&wac_i2c->client->dev,
					 "%s: i2c fail, retry, %d\n",
				      __func__, __LINE__);
			continue;
		}

		msleep(200);
		ret = wacom_i2c_recv(wac_i2c, buf, 5, false);
		if (ret < 0) {
			dev_err(&wac_i2c->client->dev,
					 "%s: i2c fail, retry, %d\n",
					 __func__, __LINE__);
			continue;
		} else if (buf[0] == 0x1f)
			break;
		dev_info(&wac_i2c->client->dev,
				 "%s: checksum retry\n",
				 __func__);
	}

	if (ret >= 0) {
		dev_info(&wac_i2c->client->dev,
				 "%s: received checksum %x, %x, %x, %x, %x\n",
				__func__, buf[0], buf[1],
				buf[2], buf[3], buf[4]);
	}

	for (i = 0; i < 5; ++i) {
		if (buf[i] != Firmware_checksum[i]) {
		dev_info(&wac_i2c->client->dev,
				 "%s: checksum fail %dth %x %x\n",
				__func__, i, buf[i],
				Firmware_checksum[i]);
			break;
		}
	}

	wac_i2c->checksum_result = (5 == i);

	return ret;
}
Example #11
0
bool flash_devcieType(struct wacom_i2c *wac_i2c)
{
    int rv;
    u8 buf[4];
    u16 len;

    len = 0;
    buf[len++] = 4;
    buf[len++] = 0;
    buf[len++] = 0x32;
    buf[len++] = CMD_GET_FEATURE;

    rv = wacom_i2c_send(wac_i2c, buf, len, false);
    if (rv < 0) {
        pr_err("wacom: %s(%d) %d\n",
               __func__, rv, __LINE__);
        return false;
    }

    len = 0;
    buf[len++] = 5;
    buf[len++] = 0;

    rv = wacom_i2c_send(wac_i2c, buf, len, false);
    if (rv < 0) {
        pr_err("wacom: %s(%d) %d\n",
               __func__, rv, __LINE__);
        return false;
    }

    rv = wacom_i2c_recv(wac_i2c, buf, 4, false);
    if (rv < 0) {
        pr_err("wacom: %s(%d) %d\n",
               __func__, rv, __LINE__);
        return false;
    }

    return true;
}
static bool flash_write_block(struct wacom_i2c *wac_i2c, char *flash_data,
			      unsigned long ulAddress, u8 * pcommand_id,
			      int *ECH)
{
	const int MAX_COM_SIZE = (16 + FLASH_BLOCK_SIZE + 2);	//16: num of command[0] to command[15]
	//FLASH_BLOCK_SIZE: unit to erase the block
	//Num of Last 2 checksums
	u8 command[300];
	unsigned char sum = 0;
	int ret, i;

	command[0] = 4;		/* Command Register-LSB */
	command[1] = 0;		/* Command Register-MSB */
	command[2] = 0x37;	/* Command-LSB, ReportType:Feature(11) ReportID:7 */
	command[3] = CMD_SET_FEATURE;	/* Command-MSB, SET_REPORT */
	command[4] = 5;		/* Data Register-LSB */
	command[5] = 0;		/* Data-Register-MSB */
	command[6] = 76;	/* Length Field-LSB */
	command[7] = 0;		/* Length Field-MSB */
	command[8] = BOOT_CMD_REPORT_ID;	/* Report:ReportID */
	command[9] = BOOT_WRITE_FLASH;	/* Report:program  command */
	command[10] = *ECH = ++(*pcommand_id);	/* Report:echo */
	command[11] = ulAddress & 0x000000ff;
	command[12] = (ulAddress & 0x0000ff00) >> 8;
	command[13] = (ulAddress & 0x00ff0000) >> 16;
	command[14] = (ulAddress & 0xff000000) >> 24;	/* Report:address(4bytes) */
	command[15] = 8;	/* Report:size(8*8=64) */

	sum = 0;
	for (i = 4; i < 16; i++)
		sum += command[i];
	command[MAX_COM_SIZE - 2] = ~sum + 1;	/* Report:command checksum */

	sum = 0;
	for (i = 16; i < (FLASH_BLOCK_SIZE + 16); i++) {
		command[i] = flash_data[ulAddress + (i - 16)];
		sum += flash_data[ulAddress + (i - 16)];
	}

	command[MAX_COM_SIZE - 1] = ~sum + 1;	/* Report:data checksum */

	ret =
	    wacom_i2c_send(wac_i2c, command, (BOOT_CMD_SIZE + 4),
			   WACOM_I2C_MODE_BOOT);
	if (ret < 0) {
		printk(KERN_DEBUG"epen:%s 1 ret:%d \n", __func__, ret);
		return false;
	}

	return true;
}
static bool flash_end(struct wacom_i2c *wac_i2c)
{
	int rv, ECH;
	unsigned char command[CMD_SIZE];

	command[0] = 4;
	command[1] = 0;
	command[2] = 0x37;
	command[3] = CMD_SET_FEATURE;
	command[4] = 5;
	command[5] = 0;
	command[6] = 5;
	command[7] = 0;
	command[8] = BOOT_CMD_REPORT_ID;
	command[9] = BOOT_EXIT;
	command[10] = ECH = 7;
#if defined(CONFIG_EPEN_WACOM_G9PLL) || defined(CONFIG_EPEN_WACOM_G10PM) \
	|| defined(CONFIG_EPEN_WACOM_W9012)
	rv = wacom_i2c_send(wac_i2c, command, 11, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG"epen:%s 2 rv:%d \n", __func__, rv);
		return false;
	}
#elif defined(CONFIG_EPEN_WACOM_G9PL)
	rv = wacom_i2c_send(wac_i2c, command, 4, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:1 rv:%d\n", rv);
		return false;
	}
	rv = wacom_i2c_send(wac_i2c, command + 4, 7, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:2 rv:%d\n", rv);
		return false;
	}
#endif

	return true;
}
Example #14
0
bool flash_end(struct wacom_i2c *wac_i2c)
{
    int rv, ECH;
    u8 buf[4];
    u16 len;
    unsigned char command[CMD_SIZE];

    len = 0;
    buf[len++] = 4;
    buf[len++] = 0;
    buf[len++] = 0x37;
    buf[len++] = CMD_SET_FEATURE;

    rv = wacom_i2c_send(wac_i2c, buf, len, false);
    if (rv < 0) {
        pr_err("wacom: %s(%d) %d\n",
               __func__, rv, __LINE__);
        return false;
    }

    command[0] = 5;
    command[1] = 0;
    command[2] = 5;
    command[3] = 0;
    command[4] = BOOT_CMD_REPORT_ID;
    command[5] = BOOT_EXIT;
    command[6] = ECH = 7;

    rv = wacom_i2c_send(wac_i2c, command, 7, false);
    if (rv < 0) {
        pr_err("wacom: %s(%d) %d\n",
               __func__, rv, __LINE__);
        return false;
    }

    return true;
}
int wacom_checksum(struct wacom_i2c *wac_i2c)
{
	int ret = 0, retry = 10;
	int i = 0;
	u8 buf[5] = {0, };

	buf[0] = COM_CHECKSUM;

	while (retry--) {
		ret = wacom_i2c_send(wac_i2c, &buf[0], 1, false);
		if (ret < 0) {
			printk(KERN_DEBUG
			       "epen:i2c fail, retry, %d\n",
			       __LINE__);
			continue;
		}

		msleep(200);
		ret = wacom_i2c_recv(wac_i2c, buf, 5, false);
		if (ret < 0) {
			printk(KERN_DEBUG
			       "epen:i2c fail, retry, %d\n",
			       __LINE__);
			continue;
		} else if (buf[0] == 0x1f)
			break;
		printk(KERN_DEBUG "epen:checksum retry\n");
	}

	if (ret >= 0) {
		printk(KERN_DEBUG
		       "epen:received checksum %x, %x, %x, %x, %x\n",
		       buf[0], buf[1], buf[2], buf[3], buf[4]);
	}

	for (i = 0; i < 5; ++i) {
		if (buf[i] != fw_chksum[i]) {
			printk(KERN_DEBUG
			       "epen:checksum fail %dth %x %x\n", i,
			       buf[i], fw_chksum[i]);
			break;
		}
	}

	wac_i2c->checksum_result = (5 == i);

	return ret;
}
int wacom_i2c_modecheck(struct wacom_i2c *wac_i2c)
{
	u8 buf = COM_QUERY;
	int ret;
	int mode = WACOM_I2C_MODE_NORMAL;

	ret = wacom_i2c_send(wac_i2c, &buf, 1, false);
	if (ret < 0) {
		mode = WACOM_I2C_MODE_BOOT;
	}
	else{
		mode = WACOM_I2C_MODE_NORMAL;
	}
	printk(KERN_DEBUG "epen:I2C send at usermode(%d)\n", ret);
	return mode;
}
Example #17
0
static void wac_statecheck_work(struct work_struct *work)
{
	int ret, i;
	char buf, test[10];
	struct wacom_i2c *wac_i2c =
	    container_of(work, struct wacom_i2c, wac_statecheck_work.work);
	buf = COM_QUERY;
	printk(KERN_DEBUG "epen:%s\n", __func__);

	if (wake_lock_active(&wac_i2c->wakelock))
		return;

#ifdef BATTERY_SAVING_MODE
	if (wac_i2c->battery_saving_mode
		&& wac_i2c->pen_insert) {
		printk(KERN_DEBUG "epen:escaped from wacom check mode\n");
		printk(KERN_DEBUG "        becase pen has inserted at lpm\n");
		return;
	}
#endif

#if defined(CONFIG_TARGET_LOCALE_KOR)
#if defined(CONFIG_MACH_T0) && defined(CONFIG_TDMB_ANT_DET)
	ret = gpio_get_value(wac_i2c->wac_pdata->gpio_esd_check);
	if (ret == 0) {
		printk(KERN_DEBUG "epen:skip wacom state checking\n");
		printk(KERN_DEBUG "        becase ANT has closed\n");
		schedule_delayed_work(&wac_i2c->wac_statecheck_work, HZ * 30);
		return;
	}
#endif
#endif

	ret = wacom_i2c_send(wac_i2c, &buf, sizeof(buf), false);
	if (ret > 0)
		printk(KERN_INFO "epen:buf:%d, sent:%d\n", buf, ret);
	else {
		printk(KERN_ERR "epen:Digitizer is not active\n");
		wac_i2c->wac_pdata->suspend_platform_hw();
		msleep(200);
		wacom_power_on(wac_i2c);
		printk(KERN_ERR "epen:wacom reset done\n");
	}

	schedule_delayed_work(&wac_i2c->wac_statecheck_work, HZ * 30);
}
Example #18
0
static ssize_t epen_sampling_rate_store(struct device *dev,
					struct device_attribute *attr,
					const char *buf, size_t count)
{
	struct wacom_i2c *wac_i2c = dev_get_drvdata(dev);
	int value;
	char mode;

	if (sscanf(buf, "%d", &value) == 1) {
		switch (value) {
		case 0:
			mode = COM_SAMPLERATE_STOP;
			break;
		case 40:
			mode = COM_SAMPLERATE_40;
			break;
		case 80:
			mode = COM_SAMPLERATE_80;
			break;
		case 133:
			mode = COM_SAMPLERATE_133;
			break;
		default:
			pr_err("epen:Invalid sampling rate value\n");
			count = -1;
			goto fail;
		}

		wacom_enable_irq(wac_i2c, false);
		if (1 == wacom_i2c_send(wac_i2c, &mode, 1, false)) {
			printk(KERN_DEBUG "epen:sampling rate %d\n", value);
			msleep(100);
		} else {
			pr_err("epen:I2C write error\n");
			wacom_enable_irq(wac_i2c, true);
			count = -1;
		}
		wacom_enable_irq(wac_i2c, true);

	} else {
		pr_err("epen:can't get sampling rate data\n");
		count = -1;
	}
 fail:
	return count;
}
static bool flash_security_unlock(struct wacom_i2c *wac_i2c, int *status)
{
	int rv, ECH;
	u8 buf[4];
	u16 len;
	unsigned char command[CMD_SIZE];
	unsigned char response[RSP_SIZE];

	len = 0;
	buf[len++] = 4;
	buf[len++] = 0;
	buf[len++] = 0x37;
	buf[len++] = CMD_SET_FEATURE;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:1 rv:%d\n", rv);
		return false;
	}

	command[0] = 5;
	command[1] = 0;
	command[2] = 5;
	command[3] = 0;
	command[4] = BOOT_CMD_REPORT_ID;
	command[5] = BOOT_SECURITY_UNLOCK;
	command[6] = ECH = 7;

	rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:2 rv:%d\n", rv);
		return false;
	}

	usleep_range(10000, 10000);

	len = 0;
	buf[len++] = 4;
	buf[len++] = 0;
	buf[len++] = 0x38;
	buf[len++] = CMD_GET_FEATURE;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:3 rv:%d\n", rv);
		return 0;
	}

	len = 0;
	buf[len++] = 5;
	buf[len++] = 0;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:4 rv:%d\n", rv);
		return false;
	}

	usleep_range(1000, 1000);

	rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
		WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:5 rv:%d\n", rv);
		return false;
	}

	if ((response[3] != SEC_CMD) || (response[4] != ECH))
		return false;

	*status = (int)response[5];

	return true;
}
Example #20
0
bool flash_query(struct wacom_i2c *wac_i2c)
{
    int rv, ECH;
    u8 buf[4];
    u16 len;
    unsigned char command[CMD_SIZE];
    unsigned char response[RSP_SIZE];

    len = 0;
    buf[len++] = 4;
    buf[len++] = 0;
    buf[len++] = 0x37;
    buf[len++] = CMD_SET_FEATURE;

    pr_info(
        "wacom: %s started buf[3]:%d len:%d\n",
        __func__, buf[3], len);
    rv = wacom_i2c_send(wac_i2c, buf, len, false);
    if (rv < 0) {
        pr_err("wacom: %s(%d) %d\n",
               __func__, rv, __LINE__);
        return false;
    }

    command[0] = 5;
    command[1] = 0;
    command[2] = 5;
    command[3] = 0;
    command[4] = BOOT_CMD_REPORT_ID;
    command[5] = BOOT_QUERY;
    command[6] = ECH = 7;

    rv = wacom_i2c_send(wac_i2c, command, 7, false);
    if (rv < 0) {
        pr_err("wacom: %s(%d) %d\n",
               __func__, rv, __LINE__);
        return false;
    }

    usleep(10000);

    len = 0;
    buf[len++] = 4;
    buf[len++] = 0;
    buf[len++] = 0x38;
    buf[len++] = CMD_GET_FEATURE;

    rv = wacom_i2c_send(wac_i2c, buf, len, false);
    if (rv < 0) {
        pr_err("wacom: %s(%d) %d\n",
               __func__, rv, __LINE__);
        return false;
    }

    len = 0;
    buf[len++] = 5;
    buf[len++] = 0;

    rv = wacom_i2c_send(wac_i2c, buf, len, false);
    if (rv < 0) {
        pr_err("wacom: %s(%d) %d\n",
               __func__, rv, __LINE__);
        return false;
    }

    rv = wacom_i2c_recv(wac_i2c, response,
                        BOOT_RSP_SIZE, false);
    if (rv < 0) {
        pr_err("wacom: %s(%d) %d\n",
               __func__, rv, __LINE__);
        return false;
    }

    if ((response[3] != QUERY_CMD) ||
            (response[4] != ECH)) {
        pr_err("wacom: %s res3:%d res4:%d\n", __func__,
               response[3], response[4]);
        return false;
    }
    if (response[5] != QUERY_RSP) {
        pr_err("wacom: %s res5:%d\n", __func__, response[5]);
        return false;
    }

    return true;
}
static ssize_t epen_connection_show(struct device *dev,
					 struct device_attribute *attr,
					 char *buff)
{
	struct wacom_i2c *wac_i2c = dev_get_drvdata(dev);
	u8 cmd = 0;
	u8 buf[2] = {0,};
	int ret = 0, cnt = 10;

	disable_irq(wac_i2c->client->irq);

	cmd = WACOM_I2C_STOP;
	ret = wacom_i2c_send(wac_i2c, &cmd, 1, false);
	if (ret <= 0) {
		dev_err(&wac_i2c->client->dev,
			 "%s: failed to send stop command\n",
			 __func__);
		goto grid_check_error;
	}

	cmd = WACOM_I2C_GRID_CHECK;
	ret = wacom_i2c_send(wac_i2c, &cmd, 1, false);
	if (ret <= 0) {
		dev_err(&wac_i2c->client->dev,
			 "%s: failed to send stop command\n",
			 __func__);
		goto grid_check_error;
	}

	cmd = WACOM_STATUS;
	do {
		msleep(50);
		if (1 == wacom_i2c_send(wac_i2c, &cmd, 1, false)) {
			if (2 == wacom_i2c_recv(wac_i2c,
						buf, 2, false)) {
				switch (buf[0]) {
				/*
				*	status value
				*	0 : data is not ready
				*	1 : PASS
				*	2 : Fail (coil function error)
				*	3 : Fail (All coil function error)
				*/
				case 1:
				case 2:
				case 3:
					cnt = 0;
					break;

				default:
					break;
				}
			}
		}
	} while (cnt--);

	dev_info(&wac_i2c->client->dev,
			 "%s : status: %x, error code: %x\n",
		       __func__, buf[0], buf[1]);

grid_check_error:
	cmd = WACOM_I2C_STOP;
	ret = wacom_i2c_send(wac_i2c, &cmd, 1, false);
	if (ret <= 0)
		dev_err(&wac_i2c->client->dev,
			 "%s: failed to send stop command\n",
			 __func__);

	cmd = WACOM_I2C_START;
	wacom_i2c_send(wac_i2c, &cmd, 1, false);
	if (ret <= 0)
		dev_err(&wac_i2c->client->dev,
			 "%s: failed to send stop command\n",
			 __func__);

	enable_irq(wac_i2c->client->irq);

	if ((buf[0] == 0x1) && (buf[1] == 0))
		return sprintf(buff, "%s\n", "OK");
	else
		return sprintf(buff, "%s\n", "NG");
}
static bool flash_verify(struct wacom_i2c *wac_i2c,
	unsigned char *flash_data, size_t data_size,
	unsigned long start_address,
	unsigned long *max_address, int mpuType)
{
	int ECH;
	unsigned long ulAddress;
	bool rv;
	unsigned long pageNo = 0;
	u8 command_id = 0;
	printk(KERN_DEBUG "epen:verify starts\n");
	for (ulAddress = start_address; ulAddress < *max_address;
		ulAddress += FLASH_BLOCK_SIZE) {
		const int MAX_CMD_SIZE = 12 + FLASH_BLOCK_SIZE + 2;
		unsigned char buf[300];
		unsigned char sum;
		int len;
		unsigned int i, j;
		unsigned char command[MAX_CMD_SIZE];
		unsigned char response[RSP_SIZE];

		len = 0;
		buf[len++] = 4;
		buf[len++] = 0;
		buf[len++] = 0x37;
		buf[len++] = CMD_SET_FEATURE;

		rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:1 rv:%d\n", rv);
			return false;
		}

		command[0] = 5;
		command[1] = 0;
		command[2] = 76;
		command[3] = 0;
		command[4] = BOOT_CMD_REPORT_ID;
		command[5] = BOOT_VERIFY_FLASH;
		command[6] = ECH = ++command_id;
		command[7] = ulAddress & 0x000000ff;
		command[8] = (ulAddress & 0x0000ff00) >> 8;
		command[9] = (ulAddress & 0x00ff0000) >> 16;
		command[10] = (ulAddress & 0xff000000) >> 24;
		command[11] = 8;

		sum = 0;
		for (j = 0; j < 12; j++)
			sum += command[j];
		command[MAX_CMD_SIZE - 2] = ~sum + 1;

		sum = 0;
		for (i = 12; i < (FLASH_BLOCK_SIZE + 12); i++) {
			command[i] = flash_data[ulAddress + (i - 12)];
			sum += flash_data[ulAddress + (i - 12)];
		}
		command[MAX_CMD_SIZE - 1] = ~sum + 1;

		rv = wacom_i2c_send(wac_i2c, command, BOOT_CMD_SIZE,
			WACOM_I2C_MODE_BOOT);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:2 rv:%d\n", rv);
			return false;
		}

		if (ulAddress <= 0x0ffff)
			ndelay(250000);
		else if (ulAddress >= 0x10000 && ulAddress <= 0x20000)
			ndelay(350000);
		else
			usleep_range(10000, 10000);

		len = 0;
		buf[len++] = 4;
		buf[len++] = 0;
		buf[len++] = 0x38;
		buf[len++] = CMD_GET_FEATURE;

		rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:3 rv:%d\n", rv);
			return false;
		}

		len = 0;
		buf[len++] = 5;
		buf[len++] = 0;

		rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:4 rv:%d\n", rv);
			return false;
		}

		rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
			WACOM_I2C_MODE_BOOT);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:5 rv:%d\n", rv);
			return false;
		}

		if ((response[3] != VERIFY_CMD) ||
			(response[4] != ECH) || (response[5] != ACK)) {
				printk(KERN_DEBUG "epen:res3:%d res4:%d res5:%d\n",
					response[3], response[4], response[5]);
				return false;
		}
		pageNo++;
	}

	return true;
}
static bool flash_query(struct wacom_i2c *wac_i2c)
{
	int rv, ECH;
	u8 buf[4];
	u16 len;
	unsigned char command[CMD_SIZE];
	unsigned char response[RSP_SIZE];

	len = 0;
	buf[len++] = 4;
	buf[len++] = 0;
	buf[len++] = 0x37;
	buf[len++] = CMD_SET_FEATURE;

	printk(KERN_DEBUG "epen:%s\n", __func__);
	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:1 rv:%d\n", rv);
		return false;
	}

	command[0] = 5;
	command[1] = 0;
	command[2] = 5;
	command[3] = 0;
	command[4] = BOOT_CMD_REPORT_ID;
	command[5] = BOOT_QUERY;
	command[6] = ECH = 7;

	rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:2 rv:%d\n", rv);
		return false;
	}

	len = 0;
	buf[len++] = 4;
	buf[len++] = 0;
	buf[len++] = 0x38;
	buf[len++] = CMD_GET_FEATURE;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:3 rv:%d\n", rv);
		return false;
	}

	len = 0;
	buf[len++] = 5;
	buf[len++] = 0;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:4 rv:%d\n", rv);
		return false;
	}

#ifdef CONFIG_EPEN_WACOM_G9PL
	usleep_range(10000, 10000);
#endif

	rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
			    WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:5 rv:%d\n", rv);
		return false;
	}

	if ((response[3] != QUERY_CMD) || (response[4] != ECH)) {
		printk(KERN_DEBUG "epen:res3:%d res4:%d\n", response[3],
		       response[4]);
		return false;
	}
	if (response[5] != QUERY_RSP) {
		printk(KERN_DEBUG "epen:res5:%d\n", response[5]);
		return false;
	}

	return true;
}
int wacom_i2c_query(struct wacom_i2c *wac_i2c)
{
	struct wacom_features *wac_feature = wac_i2c->wac_feature;
	int ret;
	u8 buf;
	u8 data[9] = {0, };
	int i = 0;
	int query_limit = 10;

	buf = COM_QUERY;

	for (i = 0; i < query_limit; i++) {
		ret = wacom_i2c_send(wac_i2c, &buf, 1, false);
		if (ret < 0) {
			printk(KERN_ERR"[E-PEN] I2C send failed(%d)\n", ret);
			continue;
		}
		msleep(100);
		ret = wacom_i2c_recv(wac_i2c, data, COM_QUERY_NUM, false);
		if (ret < 0) {
			printk(KERN_ERR"[E-PEN] I2C recv failed(%d)\n", ret);
			continue;
		}
		printk(KERN_INFO "[E-PEN] %s: %dth ret of wacom query=%d\n",
		       __func__, i, ret);
		if (COM_QUERY_NUM == ret) {
			if (0x0f == data[0]) {
				wac_feature->fw_version =
					((u16) data[7] << 8) + (u16) data[8];
				break;
			} else {
				printk(KERN_NOTICE
				       "[E-PEN] %X, %X, %X, %X, %X, %X, %X, fw=0x%x\n",
				       data[0], data[1], data[2], data[3],
				       data[4], data[5], data[6],
				       wac_feature->fw_version);
			}
		}
	}

#if defined(CONFIG_MACH_Q1_BD)\
	|| defined(CONFIG_MACH_P4NOTE)\
	|| defined(CONFIG_MACH_T0)
	wac_feature->x_max = (u16) WACOM_MAX_COORD_X;
	wac_feature->y_max = (u16) WACOM_MAX_COORD_Y;
#else
	wac_feature->x_max = ((u16) data[1] << 8) + (u16) data[2];
	wac_feature->y_max = ((u16) data[3] << 8) + (u16) data[4];
#endif
	wac_feature->pressure_max = (u16) data[6] + ((u16) data[5] << 8);

#if defined(COOR_WORK_AROUND)
	if (i == 10 || ret < 0) {
		printk(KERN_NOTICE "[E-PEN] COOR_WORK_AROUND is applied\n");
		printk(KERN_NOTICE
		       "[E-PEN] %X, %X, %X, %X, %X, %X, %X, %X, %X\n", data[0],
		       data[1], data[2], data[3], data[4], data[5], data[6],
		       data[7], data[8]);
		wac_feature->x_max = (u16) WACOM_MAX_COORD_X;
		wac_feature->y_max = (u16) WACOM_MAX_COORD_Y;
		wac_feature->pressure_max = (u16) WACOM_MAX_PRESSURE;
#ifdef CONFIG_MACH_T0
		wac_feature->fw_version = 0;
#else
		wac_feature->fw_version = 0xFF;
#endif
	}
#endif

	printk(KERN_NOTICE "[E-PEN] x_max=0x%X\n", wac_feature->x_max);
	printk(KERN_NOTICE "[E-PEN] y_max=0x%X\n", wac_feature->y_max);
	printk(KERN_NOTICE "[E-PEN] pressure_max=0x%X\n",
	       wac_feature->pressure_max);
	printk(KERN_NOTICE "[E-PEN] fw_version=0x%X (d7:0x%X,d8:0x%X)\n",
	       wac_feature->fw_version, data[7], data[8]);
	printk(KERN_NOTICE "[E-PEN] %X, %X, %X, %X, %X, %X, %X, %X, %X\n",
	       data[0], data[1], data[2], data[3], data[4], data[5], data[6],
	       data[7], data[8]);

	if ((i == 10) && (ret < 0)) {
		printk(KERN_DEBUG"[E-PEN] %s, failed\n", __func__);
		wac_i2c->query_status = false;
		return ret;
	}
	wac_i2c->query_status = true;

#if defined(CONFIG_MACH_P4NOTE)
	wacom_checksum(wac_i2c);
#endif

	return 0;
}
static bool flash_blver(struct wacom_i2c *wac_i2c, int *blver)
{
	int rv, ECH;
	u8 buf[4];
	u16 len;
	unsigned char command[CMD_SIZE];
	unsigned char response[RSP_SIZE];

	len = 0;
	buf[len++] = 4;
	buf[len++] = 0;
	buf[len++] = 0x37;
	buf[len++] = CMD_SET_FEATURE;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:1 rv:%d\n", rv);
		return false;
	}

	command[0] = 5;
	command[1] = 0;
	command[2] = 5;
	command[3] = 0;
	command[4] = BOOT_CMD_REPORT_ID;
	command[5] = BOOT_BLVER;
	command[6] = ECH = 7;

	rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:2 rv:%d\n", rv);
		return false;
	}

	usleep_range(10000, 10000);

	len = 0;
	buf[len++] = 4;
	buf[len++] = 0;
	buf[len++] = 0x38;
	buf[len++] = CMD_GET_FEATURE;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:3 rv:%d\n", rv);
		return false;
	}

	len = 0;
	buf[len++] = 5;
	buf[len++] = 0;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:4 rv:%d\n", rv);
		return false;
	}

#ifdef CONFIG_EPEN_WACOM_G9PL
	usleep_range(10000, 10000);
#else
	usleep_range(1000, 1000);
#endif

	rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
			    WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:5 rv:%d\n", rv);
		return false;
	}

	if ((response[3] != BOOT_CMD) || (response[4] != ECH))
		return false;

	*blver = (int)response[5];

	return true;
}
static bool flash_erase(struct wacom_i2c *wac_i2c,
			int *eraseBlock, int num)
{
	int rv, ECH;
	unsigned char sum;
	unsigned char buf[72];
	unsigned char cmd_chksum;
	u16 len;
	int i, j;
	unsigned char command[CMD_SIZE];
	unsigned char response[RSP_SIZE];

	for (i = 0; i < num; i++) {
		/*msleep(500);*/
retry:
		if (epen_debug)
			printk(KERN_DEBUG"epen:erase count %d\n", i);
		len = 0;
		buf[len++] = 4;
		buf[len++] = 0;
		buf[len++] = 0x37;
		buf[len++] = CMD_SET_FEATURE;

		rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:failing 1:%d\n", i);
			return false;
		}

		command[0] = 5;
		command[1] = 0;
		command[2] = 7;
		command[3] = 0;
		command[4] = BOOT_CMD_REPORT_ID;
		command[5] = BOOT_ERASE_FLASH;
		command[6] = ECH = i;
		command[7] = *eraseBlock;
		eraseBlock++;

		sum = 0;
		for (j = 0; j < 8; j++)
			sum += command[j];
		cmd_chksum = ~sum + 1;
		command[8] = cmd_chksum;

		rv = wacom_i2c_send(wac_i2c, command, 9, WACOM_I2C_MODE_BOOT);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:failing 2:%d\n", i);
			return false;
		}

#ifdef CONFIG_EPEN_WACOM_G9PL
		switch (i) {
		case 0:
		case 1:
			msleep(3000);
			break;
		case 2:
			msleep(5000);
			break;
		case 3:
			msleep(500);
			break;
		default:
			msleep(5000);
			break;
		}
#else
		msleep(300);
#endif

		len = 0;
		buf[len++] = 4;
		buf[len++] = 0;
		buf[len++] = 0x38;
		buf[len++] = CMD_GET_FEATURE;

		rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:failing 3:%d\n", i);
			return false;
		}

		len = 0;
		buf[len++] = 5;
		buf[len++] = 0;

		rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:failing 4:%d\n", i);
			return false;
		}

		rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
				    WACOM_I2C_MODE_BOOT);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:failing 5:%d\n", i);
			return false;
		}

		if ((response[3] != ERS_CMD) || (response[4] != ECH)) {
			printk(KERN_DEBUG "epen:failing 6:%d\n", i);
			return false;
		}

		if (response[5] == 0x80) {
			printk(KERN_DEBUG "epen:retry\n");
			goto retry;
		}
		if (response[5] != ACK) {
			printk(KERN_DEBUG "epen:failing 7:%d res5:%d\n", i,
			       response[5]);
			return false;
		}
	}
	return true;
}
static int wacom_flash_cmd(struct wacom_i2c *wac_i2c)
{
	int rv, len;
	u8 buf[10];

#if defined(CONFIG_EPEN_WACOM_G9PL) \
	|| defined(CONFIG_EPEN_WACOM_G9PLL) \
	|| defined(CONFIG_EPEN_WACOM_G10PM) \
	|| defined(CONFIG_EPEN_WACOM_W9012)

		buf[0] = 0x0d;
		buf[1] = FLASH_START0;
		buf[2] = FLASH_START1;
		buf[3] = FLASH_START2;
		buf[4] = FLASH_START3;
		buf[5] = FLASH_START4;
		buf[6] = FLASH_START5;
		buf[7] = 0x0d;

		len = 8;
		rv = i2c_master_send(wac_i2c->client, buf, len);
#else
	int i;
	bool i2c_mode = WACOM_I2C_MODE_BOOT;

	for (i = 0; i < 2; ++i) {
		len = 0;
		buf[len++] = 4;
		buf[len++] = 0;
		buf[len++] = 0x32;
		buf[len++] = CMD_SET_FEATURE;

		rv = wacom_i2c_send(wac_i2c, buf, len, i2c_mode);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:fail change to normal:%d\n",
			       rv);

			i2c_mode = WACOM_I2C_MODE_NORMAL;
			continue;
		}

		len = 0;
		buf[len++] = 5;
		buf[len++] = 0;
		buf[len++] = 4;
		buf[len++] = 0;
		buf[len++] = 2;
		buf[len++] = 2;

		rv = wacom_i2c_send(wac_i2c, buf, len, i2c_mode);
		if (rv < 0) {
			printk(KERN_DEBUG "epen:fail change to normal:%d\n",
			       rv);
			i2c_mode = WACOM_I2C_MODE_NORMAL;
			continue;
		}
	}
#endif
	if (rv < 0) {
		printk(KERN_ERR
			"Sending flash command failed\n");
		return -1;
	}

	printk(KERN_DEBUG "epen:flash cmd sent:%d\n", rv);
	msleep(500);

	return 0;
}
static bool is_flash_marking(struct wacom_i2c *wac_i2c,
	size_t data_size, bool *bMarking, int iMpuID)
{
	const int MAX_CMD_SIZE = (12 + FLASH_BLOCK_SIZE + 2);
	int rv, ECH;
	unsigned char flash_data[FLASH_BLOCK_SIZE];
	unsigned char buf[300];
	unsigned char sum;
	int len;
	unsigned int i, j;
	unsigned char response[RSP_SIZE];
	unsigned char command[MAX_CMD_SIZE];

	*bMarking = false;

	printk(KERN_DEBUG "epen:started\n");
	for (i = 0; i < FLASH_BLOCK_SIZE; i++)
		flash_data[i] = 0xFF;

	flash_data[56] = 0x00;

	len = 0;
	buf[len++] = 4;
	buf[len++] = 0;
	buf[len++] = 0x37;
	buf[len++] = CMD_SET_FEATURE;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:1 rv:%d\n", rv);
		return false;
	}

	command[0] = 5;
	command[1] = 0;
	command[2] = 76;
	command[3] = 0;
	command[4] = BOOT_CMD_REPORT_ID;
	command[5] = BOOT_VERIFY_FLASH;
	command[6] = ECH = 1;
	command[7] = 0xC0;
	command[8] = 0x1F;
	command[9] = 0x01;
	command[10] = 0x00;
	command[11] = 8;

	sum = 0;
	for (j = 0; j < 12; j++)
		sum += command[j];

	command[MAX_CMD_SIZE - 2] = ~sum + 1;

	sum = 0;
	printk(KERN_DEBUG "epen:start writing command\n");
	for (i = 12; i < (FLASH_BLOCK_SIZE + 12); i++) {
		command[i] = flash_data[i - 12];
		sum += flash_data[i - 12];
	}
	command[MAX_CMD_SIZE - 1] = ~sum + 1;

	printk(KERN_DEBUG "epen:sending command\n");
	rv = wacom_i2c_send(wac_i2c, command, MAX_CMD_SIZE,
		WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:2 rv:%d\n", rv);
		return false;
	}

	usleep_range(10000, 10000);

	len = 0;
	buf[len++] = 4;
	buf[len++] = 0;
	buf[len++] = 0x38;
	buf[len++] = CMD_GET_FEATURE;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:3 rv:%d\n", rv);
		return false;
	}

	len = 0;
	buf[len++] = 5;
	buf[len++] = 0;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:4 rv:%d\n", rv);
		return false;
	}

	rv = wacom_i2c_recv(wac_i2c, response, RSP_SIZE, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:5 rv:%d\n", rv);
		return false;
	}

	printk(KERN_DEBUG "epen:checking response\n");
	if ((response[3] != MARK_CMD) ||
		(response[4] != ECH) || (response[5] != ACK)) {
			printk(KERN_DEBUG "epen:fails res3:%d res4:%d res5:%d\n",
				response[3], response[4], response[5]);
			return false;
	}

	*bMarking = true;
	return true;
}
int wacom_i2c_query(struct wacom_i2c *wac_i2c)
{
	struct wacom_features *wac_feature = wac_i2c->wac_feature;
	int ret;
	u8 buf;
	u8 data[COM_QUERY_NUM] = {0, };
	int i = 0;
	const int query_limit = 3;

	buf = COM_QUERY;

	dev_info(&wac_i2c->client->dev,
			"%s: start\n", __func__);
	for (i = 0; i < query_limit; i++) {
		ret = wacom_i2c_send(wac_i2c, &buf, 1, false);
		if (ret < 0) {
			dev_err(&wac_i2c->client->dev,
				 "%s: I2C send failed(%d)\n",
				 __func__, ret);
			continue;
		}
		msleep(100);
		ret = wacom_i2c_recv(wac_i2c, data, COM_QUERY_NUM, false);
		if (ret < 0) {
			dev_err(&wac_i2c->client->dev,
				"%s: I2C recv failed(%d)\n",
				__func__, ret);
			continue;
		}
		dev_info(&wac_i2c->client->dev,
				"%s: %dth ret of wacom query=%d\n",
				__func__, i, ret);
		if (COM_QUERY_NUM != ret) {
			dev_info(&wac_i2c->client->dev,
			"%s: epen:failed to read i2c(%d)\n",
			__func__, ret);
			continue;
		}
			if (0x0f == data[0]) {
				wac_feature->fw_ic_version =
					((u16) data[7] << 8) + (u16) data[8];
				break;
			} else {
				dev_info(&wac_i2c->client->dev,
				       "%s: %X, %X, %X, %X, %X, %X, %X, fw=0x%x\n",
				       __func__,
				       data[0], data[1], data[2], data[3],
				       data[4], data[5], data[6],
				       wac_feature->fw_ic_version);
			}
		}
	wac_feature->x_max = wac_i2c->wac_pdata->max_x;
	wac_feature->y_max = wac_i2c->wac_pdata->max_y;

	wac_feature->pressure_max = (u16) data[6] + ((u16) data[5] << 8);

#if defined(COOR_WORK_AROUND)
	if (i == 10 || ret < 0) {
		dev_info(&wac_i2c->client->dev,
				"%s: COOR_WORK_AROUND is applied\n",
				__func__);
		dev_info(&wac_i2c->client->dev,
		       "%s: %X, %X, %X, %X, %X, %X, %X, %X, %X\n",
		       __func__, data[0], data[1], data[2],
		       data[3], data[4], data[5], data[6],
		       data[7], data[8]);
		wac_feature->x_max = (u16) wac_i2c->wac_pdata->max_x;
		wac_feature->y_max = (u16) wac_i2c->wac_pdata->max_y;
		wac_feature->pressure_max = (u16) wac_i2c->wac_pdata->max_pressure;
		wac_feature->fw_ic_version = 0;
	}
#endif

	dev_info(&wac_i2c->client->dev,
			"%s: x_max=0x%X, y_max=0x%X\n, pressure_max=0x%X",
			__func__, wac_feature->x_max,
			wac_feature->y_max,
			wac_feature->pressure_max);
	dev_info(&wac_i2c->client->dev,
			"%s: fw_version=0x%X (d7:0x%X,d8:0x%X)\n",
			__func__, wac_feature->fw_version,
			data[7], data[8]);
	dev_info(&wac_i2c->client->dev,
			"%s: %X, %X, %X, %X, %X, %X, %X, %X, %X\n",
			__func__, data[0], data[1], data[2],
			data[3], data[4], data[5], data[6],
			data[7], data[8]);

	if ((i == query_limit) && (ret < 0)) {
		dev_info(&wac_i2c->client->dev,
				"%s: failed\n", __func__);
		wac_i2c->query_status = false;
		return ret;
	}
	wac_i2c->query_status = true;

	return wac_feature->fw_ic_version;
}
static bool flash_write_block(struct wacom_i2c *wac_i2c, char *flash_data,
			      unsigned long ulAddress, u8 *pcommand_id)
{
	const int MAX_COM_SIZE = (12 + FLASH_BLOCK_SIZE + 2);
	int len, ECH;
	unsigned char buf[300];
	int rv;
	unsigned char sum;
	unsigned char command[MAX_COM_SIZE];
	unsigned char response[RSP_SIZE];
	unsigned int i;

	len = 0;
	buf[len++] = 4;
	buf[len++] = 0;
	buf[len++] = 0x37;
	buf[len++] = CMD_SET_FEATURE;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0)
		return false;

	command[0] = 5;
	command[1] = 0;
	command[2] = 76;
	command[3] = 0;
	command[4] = BOOT_CMD_REPORT_ID;
	command[5] = BOOT_WRITE_FLASH;
	command[6] = ECH = ++(*pcommand_id);
	command[7] = ulAddress & 0x000000ff;
	command[8] = (ulAddress & 0x0000ff00) >> 8;
	command[9] = (ulAddress & 0x00ff0000) >> 16;
	command[10] = (ulAddress & 0xff000000) >> 24;
	command[11] = 8;
	sum = 0;
	for (i = 0; i < 12; i++)
		sum += command[i];
	command[MAX_COM_SIZE - 2] = ~sum + 1;

	sum = 0;
	for (i = 12; i < (FLASH_BLOCK_SIZE + 12); i++) {
		command[i] = flash_data[ulAddress + (i - 12)];
		sum += flash_data[ulAddress + (i - 12)];
	}
	command[MAX_COM_SIZE - 1] = ~sum + 1;

	rv = wacom_i2c_send(wac_i2c, command, BOOT_CMD_SIZE,
			    WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:1 rv:%d\n", rv);
		return false;
	}

	usleep_range(10000, 10000);

	len = 0;
	buf[len++] = 4;
	buf[len++] = 0;
	buf[len++] = 0x38;
	buf[len++] = CMD_GET_FEATURE;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:2 rv:%d\n", rv);
		return false;
	}

	len = 0;
	buf[len++] = 5;
	buf[len++] = 0;

	rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:3 rv:%d\n", rv);
		return false;
	}

	rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
			    WACOM_I2C_MODE_BOOT);
	if (rv < 0) {
		printk(KERN_DEBUG "epen:4 rv:%d\n", rv);
		return false;
	}

	if ((response[3] != WRITE_CMD) ||
	    (response[4] != ECH) || response[5] != ACK)
		return false;

	return true;
}