aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Dyer <nick.dyer@itdev.co.uk>2014-07-23 15:40:09 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-07-23 17:42:08 -0400
commit4ce6fa017f48e892cc3465caa7fbb3dead5a6ca6 (patch)
treedf6ee6662152f8adc047ab675c61f042140ee629
parent50a77c658b80e7e3303e3bcec195b30e2b62d513 (diff)
Input: atmel_mxt_ts - calculate and check CRC in config file
By validating the checksum, we can identify if the configuration is corrupt. In addition, this patch writes the configuration in a short series of block writes rather than as many individual values. Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk> Acked-by: Benson Leung <bleung@chromium.org> Acked-by: Yufeng Shen <miletus@chromium.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c232
1 files changed, 177 insertions, 55 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index c6b5e7dbd942..d2feb9c771a4 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -48,6 +48,8 @@
48#define MXT_OBJECT_START 0x07 48#define MXT_OBJECT_START 0x07
49 49
50#define MXT_OBJECT_SIZE 6 50#define MXT_OBJECT_SIZE 6
51#define MXT_INFO_CHECKSUM_SIZE 3
52#define MXT_MAX_BLOCK_WRITE 256
51 53
52/* Object types */ 54/* Object types */
53#define MXT_DEBUG_DIAGNOSTIC_T37 37 55#define MXT_DEBUG_DIAGNOSTIC_T37 37
@@ -238,12 +240,15 @@ struct mxt_data {
238 unsigned int max_x; 240 unsigned int max_x;
239 unsigned int max_y; 241 unsigned int max_y;
240 bool in_bootloader; 242 bool in_bootloader;
243 u16 mem_size;
241 u32 config_crc; 244 u32 config_crc;
245 u32 info_crc;
242 u8 bootloader_addr; 246 u8 bootloader_addr;
243 247
244 /* Cached parameters from object table */ 248 /* Cached parameters from object table */
245 u8 T6_reportid; 249 u8 T6_reportid;
246 u16 T6_address; 250 u16 T6_address;
251 u16 T7_address;
247 u8 T9_reportid_min; 252 u8 T9_reportid_min;
248 u8 T9_reportid_max; 253 u8 T9_reportid_max;
249 u8 T19_reportid; 254 u8 T19_reportid;
@@ -849,6 +854,45 @@ static void mxt_update_crc(struct mxt_data *data, u8 cmd, u8 value)
849 mxt_wait_for_completion(data, &data->crc_completion, MXT_CRC_TIMEOUT); 854 mxt_wait_for_completion(data, &data->crc_completion, MXT_CRC_TIMEOUT);
850} 855}
851 856
857static void mxt_calc_crc24(u32 *crc, u8 firstbyte, u8 secondbyte)
858{
859 static const unsigned int crcpoly = 0x80001B;
860 u32 result;
861 u32 data_word;
862
863 data_word = (secondbyte << 8) | firstbyte;
864 result = ((*crc << 1) ^ data_word);
865
866 if (result & 0x1000000)
867 result ^= crcpoly;
868
869 *crc = result;
870}
871
872static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off)
873{
874 u32 crc = 0;
875 u8 *ptr = base + start_off;
876 u8 *last_val = base + end_off - 1;
877
878 if (end_off < start_off)
879 return -EINVAL;
880
881 while (ptr < last_val) {
882 mxt_calc_crc24(&crc, *ptr, *(ptr + 1));
883 ptr += 2;
884 }
885
886 /* if len is odd, fill the last byte with 0 */
887 if (ptr == last_val)
888 mxt_calc_crc24(&crc, *ptr, 0);
889
890 /* Mask to 24-bit */
891 crc &= 0x00FFFFFF;
892
893 return crc;
894}
895
852/* 896/*
853 * mxt_update_cfg - download configuration to chip 897 * mxt_update_cfg - download configuration to chip
854 * 898 *
@@ -875,9 +919,13 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
875 struct mxt_object *object; 919 struct mxt_object *object;
876 int ret; 920 int ret;
877 int offset; 921 int offset;
878 int pos; 922 int data_pos;
923 int byte_offset;
879 int i; 924 int i;
880 u32 info_crc, config_crc; 925 int cfg_start_ofs;
926 u32 info_crc, config_crc, calculated_crc;
927 u8 *config_mem;
928 size_t config_mem_size;
881 unsigned int type, instance, size; 929 unsigned int type, instance, size;
882 u8 val; 930 u8 val;
883 u16 reg; 931 u16 reg;
@@ -890,11 +938,11 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
890 goto release; 938 goto release;
891 } 939 }
892 940
893 pos = strlen(MXT_CFG_MAGIC); 941 data_pos = strlen(MXT_CFG_MAGIC);
894 942
895 /* Load information block and check */ 943 /* Load information block and check */
896 for (i = 0; i < sizeof(struct mxt_info); i++) { 944 for (i = 0; i < sizeof(struct mxt_info); i++) {
897 ret = sscanf(cfg->data + pos, "%hhx%n", 945 ret = sscanf(cfg->data + data_pos, "%hhx%n",
898 (unsigned char *)&cfg_info + i, 946 (unsigned char *)&cfg_info + i,
899 &offset); 947 &offset);
900 if (ret != 1) { 948 if (ret != 1) {
@@ -903,7 +951,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
903 goto release; 951 goto release;
904 } 952 }
905 953
906 pos += offset; 954 data_pos += offset;
907 } 955 }
908 956
909 if (cfg_info.family_id != data->info.family_id) { 957 if (cfg_info.family_id != data->info.family_id) {
@@ -918,125 +966,188 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
918 goto release; 966 goto release;
919 } 967 }
920 968
921 if (cfg_info.version != data->info.version) 969 /* Read CRCs */
922 dev_err(dev, "Warning: version mismatch!\n"); 970 ret = sscanf(cfg->data + data_pos, "%x%n", &info_crc, &offset);
923
924 if (cfg_info.build != data->info.build)
925 dev_err(dev, "Warning: build num mismatch!\n");
926
927 ret = sscanf(cfg->data + pos, "%x%n", &info_crc, &offset);
928 if (ret != 1) { 971 if (ret != 1) {
929 dev_err(dev, "Bad format: failed to parse Info CRC\n"); 972 dev_err(dev, "Bad format: failed to parse Info CRC\n");
930 ret = -EINVAL; 973 ret = -EINVAL;
931 goto release; 974 goto release;
932 } 975 }
933 pos += offset; 976 data_pos += offset;
934 977
935 /* Check config CRC */ 978 ret = sscanf(cfg->data + data_pos, "%x%n", &config_crc, &offset);
936 ret = sscanf(cfg->data + pos, "%x%n", &config_crc, &offset);
937 if (ret != 1) { 979 if (ret != 1) {
938 dev_err(dev, "Bad format: failed to parse Config CRC\n"); 980 dev_err(dev, "Bad format: failed to parse Config CRC\n");
939 ret = -EINVAL; 981 ret = -EINVAL;
940 goto release; 982 goto release;
941 } 983 }
942 pos += offset; 984 data_pos += offset;
943 985
944 if (data->config_crc == config_crc) { 986 /*
945 dev_dbg(dev, "Config CRC 0x%06X: OK\n", config_crc); 987 * The Info Block CRC is calculated over mxt_info and the object
946 ret = 0; 988 * table. If it does not match then we are trying to load the
947 goto release; 989 * configuration from a different chip or firmware version, so
990 * the configuration CRC is invalid anyway.
991 */
992 if (info_crc == data->info_crc) {
993 if (config_crc == 0 || data->config_crc == 0) {
994 dev_info(dev, "CRC zero, attempting to apply config\n");
995 } else if (config_crc == data->config_crc) {
996 dev_dbg(dev, "Config CRC 0x%06X: OK\n",
997 data->config_crc);
998 ret = 0;
999 goto release;
1000 } else {
1001 dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n",
1002 data->config_crc, config_crc);
1003 }
1004 } else {
1005 dev_warn(dev,
1006 "Warning: Info CRC error - device=0x%06X file=0x%06X\n",
1007 data->info_crc, info_crc);
948 } 1008 }
949 1009
950 dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n", 1010 /* Malloc memory to store configuration */
951 data->config_crc, config_crc); 1011 cfg_start_ofs = MXT_OBJECT_START +
1012 data->info.object_num * sizeof(struct mxt_object) +
1013 MXT_INFO_CHECKSUM_SIZE;
1014 config_mem_size = data->mem_size - cfg_start_ofs;
1015 config_mem = kzalloc(config_mem_size, GFP_KERNEL);
1016 if (!config_mem) {
1017 dev_err(dev, "Failed to allocate memory\n");
1018 ret = -ENOMEM;
1019 goto release;
1020 }
952 1021
953 while (pos < cfg->size) { 1022 while (data_pos < cfg->size) {
954 /* Read type, instance, length */ 1023 /* Read type, instance, length */
955 ret = sscanf(cfg->data + pos, "%x %x %x%n", 1024 ret = sscanf(cfg->data + data_pos, "%x %x %x%n",
956 &type, &instance, &size, &offset); 1025 &type, &instance, &size, &offset);
957 if (ret == 0) { 1026 if (ret == 0) {
958 /* EOF */ 1027 /* EOF */
959 ret = 1; 1028 break;
960 goto release;
961 } else if (ret != 3) { 1029 } else if (ret != 3) {
962 dev_err(dev, "Bad format: failed to parse object\n"); 1030 dev_err(dev, "Bad format: failed to parse object\n");
963 ret = -EINVAL; 1031 ret = -EINVAL;
964 goto release; 1032 goto release_mem;
965 } 1033 }
966 pos += offset; 1034 data_pos += offset;
967 1035
968 object = mxt_get_object(data, type); 1036 object = mxt_get_object(data, type);
969 if (!object) { 1037 if (!object) {
970 /* Skip object */ 1038 /* Skip object */
971 for (i = 0; i < size; i++) { 1039 for (i = 0; i < size; i++) {
972 ret = sscanf(cfg->data + pos, "%hhx%n", 1040 ret = sscanf(cfg->data + data_pos, "%hhx%n",
973 &val, 1041 &val,
974 &offset); 1042 &offset);
975 pos += offset; 1043 data_pos += offset;
976 } 1044 }
977 continue; 1045 continue;
978 } 1046 }
979 1047
980 if (size > mxt_obj_size(object)) { 1048 if (size > mxt_obj_size(object)) {
981 dev_err(dev, "Discarding %zu byte(s) in T%u\n", 1049 /*
982 size - mxt_obj_size(object), type); 1050 * Either we are in fallback mode due to wrong
1051 * config or config from a later fw version,
1052 * or the file is corrupt or hand-edited.
1053 */
1054 dev_warn(dev, "Discarding %zu byte(s) in T%u\n",
1055 size - mxt_obj_size(object), type);
1056 } else if (mxt_obj_size(object) > size) {
1057 /*
1058 * If firmware is upgraded, new bytes may be added to
1059 * end of objects. It is generally forward compatible
1060 * to zero these bytes - previous behaviour will be
1061 * retained. However this does invalidate the CRC and
1062 * will force fallback mode until the configuration is
1063 * updated. We warn here but do nothing else - the
1064 * malloc has zeroed the entire configuration.
1065 */
1066 dev_warn(dev, "Zeroing %zu byte(s) in T%d\n",
1067 mxt_obj_size(object) - size, type);
983 } 1068 }
984 1069
985 if (instance >= mxt_obj_instances(object)) { 1070 if (instance >= mxt_obj_instances(object)) {
986 dev_err(dev, "Object instances exceeded!\n"); 1071 dev_err(dev, "Object instances exceeded!\n");
987 ret = -EINVAL; 1072 ret = -EINVAL;
988 goto release; 1073 goto release_mem;
989 } 1074 }
990 1075
991 reg = object->start_address + mxt_obj_size(object) * instance; 1076 reg = object->start_address + mxt_obj_size(object) * instance;
992 1077
993 for (i = 0; i < size; i++) { 1078 for (i = 0; i < size; i++) {
994 ret = sscanf(cfg->data + pos, "%hhx%n", 1079 ret = sscanf(cfg->data + data_pos, "%hhx%n",
995 &val, 1080 &val,
996 &offset); 1081 &offset);
997 if (ret != 1) { 1082 if (ret != 1) {
998 dev_err(dev, "Bad format in T%d\n", type); 1083 dev_err(dev, "Bad format in T%d\n", type);
999 ret = -EINVAL; 1084 ret = -EINVAL;
1000 goto release; 1085 goto release_mem;
1001 } 1086 }
1002 pos += offset; 1087 data_pos += offset;
1003 1088
1004 if (i > mxt_obj_size(object)) 1089 if (i > mxt_obj_size(object))
1005 continue; 1090 continue;
1006 1091
1007 ret = mxt_write_reg(data->client, reg + i, val); 1092 byte_offset = reg + i - cfg_start_ofs;
1008 if (ret)
1009 goto release;
1010 1093
1094 if ((byte_offset >= 0)
1095 && (byte_offset <= config_mem_size)) {
1096 *(config_mem + byte_offset) = val;
1097 } else {
1098 dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n",
1099 reg, object->type, byte_offset);
1100 ret = -EINVAL;
1101 goto release_mem;
1102 }
1011 } 1103 }
1104 }
1012 1105
1013 /* 1106 /* Calculate crc of the received configs (not the raw config file) */
1014 * If firmware is upgraded, new bytes may be added to end of 1107 if (data->T7_address < cfg_start_ofs) {
1015 * objects. It is generally forward compatible to zero these 1108 dev_err(dev, "Bad T7 address, T7addr = %x, config offset %x\n",
1016 * bytes - previous behaviour will be retained. However 1109 data->T7_address, cfg_start_ofs);
1017 * this does invalidate the CRC and will force a config 1110 ret = 0;
1018 * download every time until the configuration is updated. 1111 goto release_mem;
1019 */ 1112 }
1020 if (size < mxt_obj_size(object)) {
1021 dev_info(dev, "Zeroing %zu byte(s) in T%d\n",
1022 mxt_obj_size(object) - size, type);
1023 1113
1024 for (i = size + 1; i < mxt_obj_size(object); i++) { 1114 calculated_crc = mxt_calculate_crc(config_mem,
1025 ret = mxt_write_reg(data->client, reg + i, 0); 1115 data->T7_address - cfg_start_ofs,
1026 if (ret) 1116 config_mem_size);
1027 goto release; 1117
1028 } 1118 if (config_crc > 0 && (config_crc != calculated_crc))
1119 dev_warn(dev, "Config CRC error, calculated=%06X, file=%06X\n",
1120 calculated_crc, config_crc);
1121
1122 /* Write configuration as blocks */
1123 byte_offset = 0;
1124 while (byte_offset < config_mem_size) {
1125 size = config_mem_size - byte_offset;
1126
1127 if (size > MXT_MAX_BLOCK_WRITE)
1128 size = MXT_MAX_BLOCK_WRITE;
1129
1130 ret = __mxt_write_reg(data->client,
1131 cfg_start_ofs + byte_offset,
1132 size, config_mem + byte_offset);
1133 if (ret != 0) {
1134 dev_err(dev, "Config write error, ret=%d\n", ret);
1135 goto release_mem;
1029 } 1136 }
1137
1138 byte_offset += size;
1030 } 1139 }
1031 1140
1032 mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE); 1141 mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
1033 1142
1034 ret = mxt_soft_reset(data); 1143 ret = mxt_soft_reset(data);
1035 if (ret) 1144 if (ret)
1036 goto release; 1145 goto release_mem;
1037 1146
1038 dev_info(dev, "Config successfully updated\n"); 1147 dev_info(dev, "Config successfully updated\n");
1039 1148
1149release_mem:
1150 kfree(config_mem);
1040release: 1151release:
1041 release_firmware(cfg); 1152 release_firmware(cfg);
1042 return ret; 1153 return ret;
@@ -1099,6 +1210,7 @@ static int mxt_get_object_table(struct mxt_data *data)
1099 int error; 1210 int error;
1100 int i; 1211 int i;
1101 u8 reportid; 1212 u8 reportid;
1213 u16 end_address;
1102 1214
1103 table_size = data->info.object_num * sizeof(struct mxt_object); 1215 table_size = data->info.object_num * sizeof(struct mxt_object);
1104 object_table = kzalloc(table_size, GFP_KERNEL); 1216 object_table = kzalloc(table_size, GFP_KERNEL);
@@ -1116,6 +1228,7 @@ static int mxt_get_object_table(struct mxt_data *data)
1116 1228
1117 /* Valid Report IDs start counting from 1 */ 1229 /* Valid Report IDs start counting from 1 */
1118 reportid = 1; 1230 reportid = 1;
1231 data->mem_size = 0;
1119 for (i = 0; i < data->info.object_num; i++) { 1232 for (i = 0; i < data->info.object_num; i++) {
1120 struct mxt_object *object = object_table + i; 1233 struct mxt_object *object = object_table + i;
1121 u8 min_id, max_id; 1234 u8 min_id, max_id;
@@ -1143,6 +1256,9 @@ static int mxt_get_object_table(struct mxt_data *data)
1143 data->T6_reportid = min_id; 1256 data->T6_reportid = min_id;
1144 data->T6_address = object->start_address; 1257 data->T6_address = object->start_address;
1145 break; 1258 break;
1259 case MXT_GEN_POWER_T7:
1260 data->T7_address = object->start_address;
1261 break;
1146 case MXT_TOUCH_MULTI_T9: 1262 case MXT_TOUCH_MULTI_T9:
1147 data->T9_reportid_min = min_id; 1263 data->T9_reportid_min = min_id;
1148 data->T9_reportid_max = max_id; 1264 data->T9_reportid_max = max_id;
@@ -1151,6 +1267,12 @@ static int mxt_get_object_table(struct mxt_data *data)
1151 data->T19_reportid = min_id; 1267 data->T19_reportid = min_id;
1152 break; 1268 break;
1153 } 1269 }
1270
1271 end_address = object->start_address
1272 + mxt_obj_size(object) * mxt_obj_instances(object) - 1;
1273
1274 if (end_address >= data->mem_size)
1275 data->mem_size = end_address + 1;
1154 } 1276 }
1155 1277
1156 data->object_table = object_table; 1278 data->object_table = object_table;