Skip to content

Commit 4e6558b

Browse files
ndyerehristev
authored andcommitted
Input: atmel_mxt_ts - verify Information Block checksum on probe
By reading the information block and the object table into a contiguous region of memory, we can verify the checksum at probe time. This means we verify that we are indeed talking to a chip that supports object protocol correctly. We also detect I2C comms problems much earlier, resulting in easier diagnosis. Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk> Acked-by: Benson Leung <bleung@chromium.org> [cyrille.pitchen@atmel.com: adapt original patch to mainline] Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com> [eugen.hristev@microchip.com: adapt original patch to 4.14] Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
1 parent 2f71557 commit 4e6558b

1 file changed

Lines changed: 26 additions & 20 deletions

File tree

drivers/input/touchscreen/atmel_mxt_ts.c

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,8 +1711,10 @@ static int mxt_parse_object_table(struct mxt_data *data,
17111711

17121712
data->msg_buf = kcalloc(data->max_reportid,
17131713
data->T5_msg_size, GFP_KERNEL);
1714-
if (!data->msg_buf)
1714+
if (!data->msg_buf) {
1715+
dev_err(&client->dev, "Failed to allocate message buffer\n");
17151716
return -ENOMEM;
1717+
}
17161718

17171719
return 0;
17181720
}
@@ -1728,43 +1730,48 @@ static int mxt_read_info_block(struct mxt_data *data)
17281730
u8 *crc_ptr;
17291731

17301732
/* If info block already allocated, free it */
1731-
if (data->raw_info_block)
1733+
if (data->raw_info_block != NULL)
17321734
mxt_free_object_table(data);
17331735

17341736
/* Read 7-byte ID information block starting at address 0 */
17351737
size = sizeof(struct mxt_info);
17361738
id_buf = kzalloc(size, GFP_KERNEL);
1737-
if (!id_buf)
1739+
if (!id_buf) {
1740+
dev_err(&client->dev, "Failed to allocate memory\n");
17381741
return -ENOMEM;
1742+
}
17391743

17401744
error = __mxt_read_reg(client, 0, size, id_buf);
1741-
if (error)
1742-
goto err_free_mem;
1745+
if (error) {
1746+
kfree(id_buf);
1747+
return error;
1748+
}
17431749

17441750
/* Resize buffer to give space for rest of info block */
17451751
num_objects = ((struct mxt_info *)id_buf)->object_num;
17461752
size += (num_objects * sizeof(struct mxt_object))
17471753
+ MXT_INFO_CHECKSUM_SIZE;
17481754

17491755
buf = krealloc(id_buf, size, GFP_KERNEL);
1756+
id_buf = buf;
17501757
if (!buf) {
1758+
dev_err(&client->dev, "Failed to allocate memory\n");
17511759
error = -ENOMEM;
17521760
goto err_free_mem;
17531761
}
1754-
id_buf = buf;
17551762

17561763
/* Read rest of info block */
17571764
error = __mxt_read_reg(client, MXT_OBJECT_START,
17581765
size - MXT_OBJECT_START,
1759-
id_buf + MXT_OBJECT_START);
1766+
buf + MXT_OBJECT_START);
17601767
if (error)
17611768
goto err_free_mem;
17621769

17631770
/* Extract & calculate checksum */
1764-
crc_ptr = id_buf + size - MXT_INFO_CHECKSUM_SIZE;
1771+
crc_ptr = buf + size - MXT_INFO_CHECKSUM_SIZE;
17651772
data->info_crc = crc_ptr[0] | (crc_ptr[1] << 8) | (crc_ptr[2] << 16);
17661773

1767-
calculated_crc = mxt_calculate_crc(id_buf, 0,
1774+
calculated_crc = mxt_calculate_crc(buf, 0,
17681775
size - MXT_INFO_CHECKSUM_SIZE);
17691776

17701777
/*
@@ -1774,13 +1781,13 @@ static int mxt_read_info_block(struct mxt_data *data)
17741781
if ((data->info_crc == 0) || (data->info_crc != calculated_crc)) {
17751782
dev_err(&client->dev,
17761783
"Info Block CRC error calculated=0x%06X read=0x%06X\n",
1777-
calculated_crc, data->info_crc);
1784+
data->info_crc, calculated_crc);
17781785
error = -EIO;
17791786
goto err_free_mem;
17801787
}
17811788

1782-
data->raw_info_block = id_buf;
1783-
data->info = (struct mxt_info *)id_buf;
1789+
data->raw_info_block = buf;
1790+
data->info = (struct mxt_info *)buf;
17841791

17851792
dev_info(&client->dev,
17861793
"Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
@@ -1789,19 +1796,19 @@ static int mxt_read_info_block(struct mxt_data *data)
17891796
data->info->build, data->info->object_num);
17901797

17911798
/* Parse object table information */
1792-
error = mxt_parse_object_table(data, id_buf + MXT_OBJECT_START);
1799+
error = mxt_parse_object_table(data, buf + MXT_OBJECT_START);
17931800
if (error) {
17941801
dev_err(&client->dev, "Error %d parsing object table\n", error);
17951802
mxt_free_object_table(data);
1796-
goto err_free_mem;
1803+
return error;
17971804
}
17981805

1799-
data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START);
1806+
data->object_table = (struct mxt_object *)(buf + MXT_OBJECT_START);
18001807

18011808
return 0;
18021809

18031810
err_free_mem:
1804-
kfree(id_buf);
1811+
kfree(buf);
18051812
return error;
18061813
}
18071814

@@ -2745,19 +2752,18 @@ static ssize_t mxt_fw_version_show(struct device *dev,
27452752
struct device_attribute *attr, char *buf)
27462753
{
27472754
struct mxt_data *data = dev_get_drvdata(dev);
2748-
struct mxt_info *info = data->info;
27492755
return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n",
2750-
info->version >> 4, info->version & 0xf, info->build);
2756+
data->info->version >> 4, data->info->version & 0xf,
2757+
data->info->build);
27512758
}
27522759

27532760
/* Hardware Version is returned as FamilyID.VariantID */
27542761
static ssize_t mxt_hw_version_show(struct device *dev,
27552762
struct device_attribute *attr, char *buf)
27562763
{
27572764
struct mxt_data *data = dev_get_drvdata(dev);
2758-
struct mxt_info *info = data->info;
27592765
return scnprintf(buf, PAGE_SIZE, "%u.%u\n",
2760-
info->family_id, info->variant_id);
2766+
data->info->family_id, data->info->variant_id);
27612767
}
27622768

27632769
static ssize_t mxt_show_instance(char *buf, int count,

0 commit comments

Comments
 (0)