From 6540b666f401c1c76ff52d0dbba96d87af047d14 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 6 Aug 2024 13:59:09 -0700 Subject: [PATCH] Add_v3_config_handling --- VERSION | 2 +- src/libmaxtouch/config.c | 1030 ++++++++++++++++++---- src/libmaxtouch/i2c_dev/i2c_dev_device.c | 397 +++++++-- src/libmaxtouch/i2c_dev/i2c_dev_device.h | 9 +- src/libmaxtouch/info_block.c | 119 ++- src/libmaxtouch/info_block.h | 36 +- src/libmaxtouch/libmaxtouch.c | 59 +- src/libmaxtouch/libmaxtouch.h | 13 +- src/libmaxtouch/sysfs/sysfs_device.c | 155 +++- src/libmaxtouch/sysfs/sysfs_device.h | 2 +- src/mxt-app/menu.c | 14 +- src/mxt-app/mxt_app.c | 13 +- src/mxt-app/mxt_app.h | 5 + src/mxt-app/self_test.c | 2 +- src/mxt-app/serial_data.c | 241 +++-- src/mxt-app/serial_data.h | 84 ++ 16 files changed, 1823 insertions(+), 358 deletions(-) create mode 100644 src/mxt-app/serial_data.h diff --git a/VERSION b/VERSION index 7b541986..6477a571 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.39 +1.40 diff --git a/src/libmaxtouch/config.c b/src/libmaxtouch/config.c index de237127..744f596b 100644 --- a/src/libmaxtouch/config.c +++ b/src/libmaxtouch/config.c @@ -39,8 +39,16 @@ #include "info_block.h" #include "utilfuncs.h" #include "msg.h" +#include "mxt-app/serial_data.h" +#include "mxt-app/buffer.h" + +#define OBP_RAW_MAGIC_V1 "OBP_RAW V1" +#define OBP_RAW_MAGIC_V2 "OBP_RAW V2" +#define OBP_RAW_MAGIC_V3 "OBP_RAW V3" +#define ENC_BLOCK_HDR "MAX_ENCRYPTION_BLOCKS" +#define ENC_HDR "ENCRYPTION" +#define ENC_BIT_MASK 0x7F -#define OBP_RAW_MAGIC "OBP_RAW V1" //****************************************************************************** /// \brief Config file types @@ -53,8 +61,9 @@ enum mxt_config_type { /// \brief Configuration data for a single object struct mxt_object_config { uint32_t type; - uint8_t instance; + uint16_t instance; uint32_t size; + uint32_t enc_size; uint16_t start_position; uint8_t *data; struct mxt_object_config *next; @@ -63,19 +72,80 @@ struct mxt_object_config { //****************************************************************************** /// \brief Device configuration struct mxt_config { + struct mxt_device mxt; struct mxt_id_info id; struct mxt_object_config *head; uint32_t info_crc; uint32_t config_crc; + int cfg_enc; + int cfg_blksize; + int cfg_version; enum mxt_config_type config_type; }; +//****************************************************************************** +/// \brief Check encryption status of device +/// \return Success, if T2 read; error if T2 not read +int mxt_check_encryption(struct mxt_device *mxt) +{ + uint8_t buf[3]; + uint32_t checksum; + int ret; + + mxt->mxt_enc.addr = mxt_get_object_address(mxt, + GEN_ENCRYPTIONSTATUS_T2, 0); + if (mxt->mxt_enc.addr == OBJECT_NOT_FOUND) + return MXT_ERROR_OBJECT_NOT_FOUND; + + ret = mxt_read_register(mxt, buf, mxt->mxt_enc.addr, 1); + + if ((buf[0] & MSGENCEN) || (buf[0] & CONFIGENCEN)) { + /* TBD may be redundant as MSBit is checked with variant ID */ + SET_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED); + + mxt_info(mxt->ctx, "Device encryption enabled\n"); + + if (buf[0] & MSGENCEN) { + SET_BIT(mxt->mxt_enc.encryption_state, MSG_ENCRYPTED); + mxt->mxt_enc.msg_enc_enabled = true; + } + else { + CLEAR_BIT(mxt->mxt_enc.encryption_state, MSG_ENCRYPTED); + mxt->mxt_enc.msg_enc_enabled = false; + } + + if (buf[0] & CONFIGENCEN) { + SET_BIT(mxt->mxt_enc.encryption_state, CFG_ENCRYPTED); + mxt->mxt_enc.enc_blocksize = 0x30; + } else { + CLEAR_BIT(mxt->mxt_enc.encryption_state, CFG_ENCRYPTED); + } + } else { + mxt->mxt_enc.encryption_state = 0x00; + } + + ret = mxt_read_register(mxt, buf, mxt->mxt_enc.addr + T2_PAYLOADCRC_OFFSET, 3); + + checksum = (buf[0] | (buf[1] << 8) | (buf[2] << 16)); + + mxt_dbg(mxt->ctx, "mxt-app: T2 Payload CRC = 0x%06X", checksum); + + ret = mxt_read_register(mxt, buf, mxt->mxt_enc.addr + T2_ENCKEYCRC_OFFSET, 3); + + checksum = (buf[0] | (buf[1] << 8) | (buf[2] << 16)); + + mxt_dbg(mxt->ctx, "mxt-app: T2 Enc Customer Key CRC = 0x%06X", checksum); + + return ret; +} + //****************************************************************************** /// \brief Determines whether the object type is used for CRC checksum calculation /// \return True if used, false if not static bool is_type_used_for_crc(const uint32_t type) { switch (type) { + case GEN_ENCRYPTIONSTATUS_T2: case GEN_MESSAGEPROCESSOR_T5: case GEN_COMMANDPROCESSOR_T6: case DEBUG_DIAGNOSTIC_T37: @@ -95,13 +165,13 @@ static bool is_type_used_for_crc(const uint32_t type) static bool mxt_object_is_volatile(uint16_t object_type) { switch (object_type) { - case DEBUG_DELTAS_T2: case DEBUG_REFERENCES_T3: case DEBUG_SIGNALS_T4: case GEN_MESSAGEPROCESSOR_T5: case GEN_COMMANDPROCESSOR_T6: case SPT_MESSAGECOUNT_T44: case GEN_DATASOURCE_T53: + case DEBUG_DIAGNOSTIC_T37: return true; default: @@ -133,42 +203,147 @@ static void mxt_free_config(struct mxt_config *cfg) static int mxt_write_object_config(struct mxt_device *mxt, const struct mxt_object_config *objcfg) { + struct t68_ctx ctx; uint8_t obj_buf[MXT_OBJECT_SIZE_MAX]; uint16_t obj_addr; uint16_t device_size; uint16_t num_bytes; - int ret; + uint8_t value = 0; + uint8_t diff = 0; + bool t38_found = false; + int ret = 0; + int i; + + if (mxt_object_is_volatile(objcfg->type)) { + ret = MXT_ERROR_OBJECT_IS_VOLATILE; + goto close_object_write; + } - if (mxt_object_is_volatile(objcfg->type)) - return MXT_ERROR_OBJECT_IS_VOLATILE; + mxt_dbg(mxt->ctx, "write_object: T%d instance %d size %d", + objcfg->type, objcfg->instance, objcfg->size); - obj_addr = mxt_get_object_address(mxt, objcfg->type, objcfg->instance); - if (obj_addr == OBJECT_NOT_FOUND) - return MXT_ERROR_OBJECT_NOT_FOUND; + if ((objcfg->type == SERIAL_DATA_COMMAND_T68) && + (objcfg->instance & 0x8000)) { + + mxt_info(mxt->ctx, "Found T68 payload"); + + ctx.t68_datatype = objcfg->instance & 0x000F; + + obj_addr = mxt_get_object_address(mxt, objcfg->type, 0); + if (obj_addr == OBJECT_NOT_FOUND) { + ret = MXT_ERROR_OBJECT_NOT_FOUND; + goto close_object_write; + } + + if (ctx.t68_datatype == 0x000C) { + /* Check if device is encrypted or not */ + if (CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED)) { + /* If either bit encrypted, do not allow programming of T68 payload */ + if (objcfg->data[32] & 0x06) { + mxt_err(mxt->ctx, "Error: Device already encrypted, cannot program T68 payload\n"); + goto close_object_write; + } + } + + if (objcfg->data[32] & 0x04) { + mxt_info(mxt->ctx, "Enabling T5 msg encryption"); + mxt->mxt_enc.msg_enc_enabled = true; + } else if (objcfg->data[32] & 0x02) { + mxt_info(mxt->ctx, "Enabling cfg encryption"); + mxt->mxt_enc.msg_enc_enabled = false; + } else if ((objcfg->data[32] & 0x06) == 0x06) { + mxt_info(mxt->ctx, "Enabling T5 msg and cfg encryption"); + mxt->mxt_enc.msg_enc_enabled = true; + } else if ((objcfg->data[32] & 0x06) == 0x00) { + /* not a scenario that should happen */ + mxt->mxt_enc.msg_enc_enabled = false; + mxt_info(mxt->ctx, "Disabling device encryption"); + } + } + + ret = mxt_buf_init(&ctx.buf); + + for (i=0; i < objcfg->size; i++) { + value = objcfg->data[i]; + ret = mxt_buf_add(&ctx.buf, value); + } + + /* Calculate position of CMD register */ + ctx.t68_size = mxt_get_object_size(mxt, SERIAL_DATA_COMMAND_T68); - /* Read object config. This is done to retain any device configuration - * remaining in trailing bytes not specified in the file. */ - memset(obj_buf, 0, sizeof(obj_buf)); - ret = mxt_read_register(mxt, obj_buf, obj_addr, + ctx.t68_data_size = ctx.t68_size - 9; + + /* Remove payload CRC, do not write to T68 */ + ctx.t68_length = objcfg->size - 4; + + /* Fill T68 payload with 0x00 padding and add to buffer */ + if (objcfg->size < ctx.t68_data_size) { + diff = ctx.t68_data_size - objcfg->size; + + for (i=0; i < diff; i++) { + ret = mxt_buf_add(&ctx.buf, 0x00); + } + } + + ret = mxt_load_t68_payload(mxt, &ctx); + + } else if (!(CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED))) { + + obj_addr = mxt_get_object_address(mxt, objcfg->type, objcfg->instance); + + if (obj_addr == OBJECT_NOT_FOUND) { + ret = MXT_ERROR_OBJECT_NOT_FOUND; + goto close_object_write; + } + + /* Read object config. This is done to retain any device configuration + * remaining in trailing bytes not specified in the file. */ + memset(obj_buf, 0, sizeof(obj_buf)); + + device_size = mxt_get_object_size(mxt, objcfg->type); + + ret = mxt_read_register(mxt, obj_buf, obj_addr, mxt_get_object_size(mxt, objcfg->type)); - if (ret) - return ret; + if (ret) + return ret; - device_size = mxt_get_object_size(mxt, objcfg->type); + device_size = mxt_get_object_size(mxt, objcfg->type); - if (device_size > objcfg->size) { - mxt_warn(mxt->ctx, "Extending config by %d bytes in T%u", + if (device_size > objcfg->size) { + mxt_warn(mxt->ctx, "Extending config by %d bytes in T%u", device_size - objcfg->size, objcfg->type); - num_bytes = objcfg->size; - } else if (objcfg->size > device_size) { - /* Either we are in fallback mode due to wrong + num_bytes = objcfg->size; + } else if (objcfg->size > device_size) { + /* Either we are in fallback mode due to wrong * config or config from a later fw version, - * or the file is corrupt or hand-edited */ - mxt_warn(mxt->ctx, "Discarding %u bytes in T%u", + * or the file is corrupt or hand-edited */ + mxt_warn(mxt->ctx, "Discarding %u bytes in T%u", objcfg->size - device_size, objcfg->type); - num_bytes = device_size; - } else { - num_bytes = device_size; + num_bytes = device_size; + } else { + num_bytes = device_size; + } + + /* Update bytes from config */ + memcpy(obj_buf, objcfg->data, num_bytes); + + } else { /* encrypted data */ + + memset(obj_buf, 0, sizeof(obj_buf)); + + obj_addr = mxt_get_object_address(mxt, objcfg->type, objcfg->instance); + if (obj_addr == OBJECT_NOT_FOUND) { + ret = MXT_ERROR_OBJECT_NOT_FOUND; + goto close_object_write; + } + + /* Add two bytes for embedded datasize */ + /* Send datasize as embedded data to driver */ + num_bytes = objcfg->size + 2; + } + + if(objcfg->type == 38) { + t38_found = true; } /* Update bytes from config */ @@ -178,10 +353,11 @@ static int mxt_write_object_config(struct mxt_device *mxt, ret = mxt_write_register(mxt, obj_buf, obj_addr, num_bytes); if (ret) { mxt_err(mxt->ctx, "Config write error, ret=%d", ret); - return ret; + goto close_object_write; } - - return MXT_SUCCESS; + +close_object_write: + return ret; } //****************************************************************************** @@ -263,6 +439,9 @@ static int mxt_read_device_config(struct mxt_device *mxt, int obj_idx, instance; int ret; + /* Restore config data from NVM and stop T70 events */ + ret = mxt_backup_config(mxt, RESTORENV_COMMAND); + /* Copy ID information */ memcpy(&cfg->id, mxt->info.id, sizeof(struct mxt_id_info)); @@ -327,25 +506,32 @@ static int mxt_read_device_config(struct mxt_device *mxt, /// \return #mxt_rc static int mxt_save_raw_file(struct libmaxtouch_ctx *ctx, const char *filename, - struct mxt_config *cfg) + struct mxt_config *cfg, uint8_t format) { struct mxt_id_info *id = &cfg->id; struct mxt_object_config *objcfg = cfg->head; + struct mxt_device mxt; + uint8_t encryption = 0; + uint8_t enc_blocksize = 0; FILE *fp; int ret; unsigned int i; + mxt = cfg->mxt; + fp = fopen(filename, "w"); if (fp == NULL) { mxt_err(ctx, "Error opening %s: %s", filename, strerror(errno)); return mxt_errno_to_rc(errno); } - ret = fprintf(fp, "OBP_RAW V1\n"); - if (ret < 0) - goto fprintf_error; + switch (format) { + case 0: + ret = fprintf(fp, "OBP_RAW V1\n"); + if (ret < 0) + goto fprintf_error; - ret = fprintf(fp, "%02X %02X %02X %02X %02X %02X %02X\n" + ret = fprintf(fp, "%02X %02X %02X %02X %02X %02X %02X\n" "%06X\n" "%06X\n", id->family, id->variant, @@ -353,8 +539,45 @@ static int mxt_save_raw_file(struct libmaxtouch_ctx *ctx, id->matrix_x_size, id->matrix_y_size, id->num_objects, cfg->info_crc, cfg->config_crc); - if (ret < 0) - goto fprintf_error; + if (ret < 0) + goto fprintf_error; + + break; + + case 3: + + ret = fprintf(fp, "OBP_RAW V3\n"); + if (ret < 0) + goto fprintf_error; + + if (CHECK_BIT(mxt.mxt_enc.encryption_state, CFG_ENCRYPTED)) { + encryption = true; + enc_blocksize = 3; + } + ret = fprintf(fp, "ENCRYPTION %d\n", encryption); + if (ret < 0) + goto fprintf_error; + + ret = fprintf(fp, "MAX_ENCRYPTION_BLOCKS %d\n", enc_blocksize); + if (ret < 0) + goto fprintf_error; + + ret = fprintf(fp, "%02X %02X %02X %02X %02X %02X %02X\n" + "%06X\n" + "%06X\n", + id->family, id->variant, + id->version, id->build, + id->matrix_x_size, id->matrix_y_size, + id->num_objects, + cfg->info_crc, cfg->config_crc); + if (ret < 0) + goto fprintf_error; + + break; + + default: + break; + } while (objcfg) { if (mxt_object_is_volatile(objcfg->type)) @@ -392,13 +615,18 @@ static int mxt_save_raw_file(struct libmaxtouch_ctx *ctx, /// \return #mxt_rc static int mxt_save_xcfg_file(struct libmaxtouch_ctx *ctx, const char *filename, - struct mxt_config *cfg) + struct mxt_config *cfg, uint8_t format) { struct mxt_id_info *id = &cfg->id; struct mxt_object_config *objcfg = cfg->head; + struct mxt_device mxt; FILE *fp; int ret; unsigned int i; + bool encryption = false; + uint8_t enc_blocksize = 0; + + mxt = cfg->mxt; fp = fopen(filename, "w"); if (fp == NULL) { @@ -416,7 +644,11 @@ static int mxt_save_xcfg_file(struct libmaxtouch_ctx *ctx, return ret; } - ret = fprintf(fp, "\n" + switch (format) { + case 0x00: + case 0x01: + + ret = fprintf(fp, "\n" "[VERSION_INFO_HEADER]\n" "FAMILY_ID=%d\n" "VARIANT=%d\n" @@ -431,8 +663,58 @@ static int mxt_save_xcfg_file(struct libmaxtouch_ctx *ctx, id->version, id->build, cfg->config_crc, cfg->info_crc, MXT_VERSION); - if (ret < 0) - goto fprintf_error; + if (ret < 0) + goto fprintf_error; + + break; + + case 0x02: + + mxt_err(ctx, "Format %x is not yet supported", format); + + case 0x03: + + /* Check encrption */ + if (CHECK_BIT(mxt.mxt_enc.encryption_state, CFG_ENCRYPTED)) { + encryption = true; + enc_blocksize = 3; + } + + ret = fprintf(fp, "\n" + "[VERSION_INFO_HEADER]\n" + "FAMILY_ID=%d\n" + "VARIANT=%d\n" + "VERSION=%d\n" + "BUILD=%d\n" + "CHECKSUM=0x%06X\n" + "INFO_BLOCK_CHECKSUM=0x%02X\n" + "[FILE_INFO_HEADER]\n" + "VERSION=3\n" + "ENCRYPTION=%x\n" + "MAX_ENCRYPTION_BLOCKS=%d\n" + "[APPLICATION_INFO_HEADER]\n" + "NAME=libmaxtouch\n" + "VERSION=%s\n", + id->family, id->variant, + id->version, id->build, + cfg->config_crc, cfg->info_crc, + encryption, enc_blocksize, + MXT_VERSION); + + if (ret < 0) + goto fprintf_error; + + break; + + case 0x04: + mxt_err(ctx, "Format %x is not yet supported", format); + + break; + + default: + break; + + } while (objcfg) { if (mxt_object_is_volatile(objcfg->type)) @@ -479,40 +761,62 @@ static int mxt_save_xcfg_file(struct libmaxtouch_ctx *ctx, //****************************************************************************** /// \brief Load configuration from .xcfg file /// \return #mxt_rc -static int mxt_load_xcfg_file(struct libmaxtouch_ctx *ctx, const char *filename, +static int mxt_load_xcfg_file(struct mxt_device *mxt, const char *filename, struct mxt_config *cfg) { FILE *fp; - int c; + struct mxt_object_config **next = &cfg->head; + struct mxt_object_config *objcfg; + struct t68_ctx t68_ctx; char object[255]; char tmp[255]; + char encryption_type[255]; char *substr; int object_id; int instance; int object_address; int object_size; int data; + int payload_crc; + int payload_size; int file_read = 0; bool ignore_line = false; + bool skip_addr_size = false; + bool add_datasize = true; + uint8_t family_id = 0; + uint8_t variant_id = 0; + uint16_t t38_addr = 0; + bool t68_not = true; int ret; - struct mxt_object_config **next = &cfg->head; - struct mxt_object_config *objcfg; + int c; cfg->config_type = CONFIG_XCFG; + t38_addr = mxt_get_object_address(mxt, SPT_USERDATA_T38, 0); + + if(t38_addr == OBJECT_NOT_FOUND) { + ret = OBJECT_NOT_FOUND; + mxt_err(mxt->ctx, "Could not find T38 object or not supported"); + return MXT_ERROR_OBJECT_NOT_FOUND; + } + fp = fopen(filename, "r"); if (fp == NULL) { - mxt_err(ctx, "Error opening %s: %s", filename, strerror(errno)); + mxt_err(mxt->ctx, "Error opening %s: %s", filename, strerror(errno)); return mxt_errno_to_rc(errno); } while (!file_read) { /* First character is expected to be '[' - skip empty lines and spaces */ c = getc(fp); + + /* Skip newline, carrage return,spaces, get next char*/ while ((c == '\n') || (c == '\r') || (c == 0x20)) c = getc(fp); + /* Always expecting starting '[' for xcfg file */ if (c != '[') { + if (c == EOF) break; @@ -521,22 +825,22 @@ static int mxt_load_xcfg_file(struct libmaxtouch_ctx *ctx, const char *filename, continue; } - mxt_err(ctx, "Parse error: expected '[', read ascii char %c!", c); + mxt_err(mxt->ctx, "Parse error: expected '[', read ascii char %c!", c); ret = MXT_ERROR_FILE_FORMAT; goto close; - } + } /* End of '[' */ if (fscanf(fp, "%[^] ]", object) != 1) { - mxt_err(ctx, "Object parse error"); + mxt_err(mxt->ctx, "Object parse error"); ret = MXT_ERROR_FILE_FORMAT; goto close; } - /* Ignore the comments and file header sections */ + /* Ignore the comments and file info header sections */ if (!strcmp(object, "COMMENTS") || !strcmp(object, "APPLICATION_INFO_HEADER")) { ignore_line = true; - mxt_dbg(ctx, "Skipping %s", object); + mxt_dbg(mxt->ctx, "Skipping %s", object); continue; } @@ -546,86 +850,222 @@ static int mxt_load_xcfg_file(struct libmaxtouch_ctx *ctx, const char *filename, if (!strcmp(object, "VERSION_INFO_HEADER")) { while (false == ignore_line) { if (fscanf(fp, "%s", tmp) != 1) { - mxt_err(ctx, "Version info header parse error"); + mxt_err(mxt->ctx, "Version info header parse error"); ret = MXT_ERROR_FILE_FORMAT; goto close; } + + if (!strncmp(tmp, "FAMILY_ID", 9)) { + sscanf(tmp, "%[^'=']=%" SCNu8, object, &family_id); + + if (family_id != mxt->info.id->family) { + mxt_err(mxt->ctx, "Family ID mismatch error"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + } + + if (!strncmp(tmp, "VARIANT", 7)) { + sscanf(tmp, "%[^'=']=%" SCNu8, object, &variant_id); + + /* Check variant before flashing */ + if ((variant_id & ENC_BIT_MASK) != + (mxt->info.id->variant & ENC_BIT_MASK)) { + mxt_err(mxt->ctx, "Variant ID mismatch error"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + } + if (!strncmp(tmp, "CHECKSUM", 8)) { sscanf(tmp, "%[^'=']=%x", object, &cfg->config_crc); - mxt_dbg(ctx, "Config CRC from file: %s", tmp); + mxt_info(mxt->ctx, "Config File Checksum: %s", tmp); ignore_line = true; } } continue; } - if (fscanf(fp, "%s", tmp) != 1) { - mxt_err(ctx, "Instance parse error"); - ret = MXT_ERROR_FILE_FORMAT; - goto close; - } + /* Extract content of file info header */ + if (!strcmp(object, "FILE_INFO_HEADER")) { + while (false == ignore_line) { + if (fscanf(fp, "%s", tmp) != 1) { + mxt_err(mxt->ctx, "Version info header parse error"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } - if (strcmp(tmp, "INSTANCE")) { - mxt_err(ctx, "Parse error, expected INSTANCE, got %s", tmp); - ret = MXT_ERROR_FILE_FORMAT; - goto close; + if (!strncmp(tmp, "VERSION", 7)) { + sscanf(tmp, "%[^'=']=%d", object, &cfg->cfg_version); + mxt_info(mxt->ctx, "Config version = %x", cfg->cfg_version); + } + + if (!strncmp(tmp, "ENCRYPTION", 10)) { + sscanf(tmp, "%[^'=']=%s", object, encryption_type); + + if (!strcmp(encryption_type, "FALSE")) { + cfg->cfg_enc = false; + } else { + cfg->cfg_enc = true; + if (mxt->conn->type == E_SYSFS_I2C) { + mxt_err(mxt->ctx, "Warning: Writing encrypted config not supported in sysfs mode\n" + "Upgrade mxt-app required or use i2c-dev mode\n"); + + return MXT_ERROR_NOT_SUPPORTED; + } + } + + if (cfg->cfg_enc) { + if (CHECK_BIT(mxt->mxt_enc.encryption_state, CFG_ENCRYPTED)) { + mxt_info(mxt->ctx, "Config and device are encrypted." + "Okay to update chip configuration."); + } else { + mxt_info(mxt->ctx, "Cannot program encrypted cfg into unencrypted device"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + + } else { + mxt_info(mxt->ctx, "Config file is unencrypted. Checking device encryption"); + if (CHECK_BIT(mxt->mxt_enc.encryption_state, CFG_ENCRYPTED)) { + mxt_info(mxt->ctx, "Cannot program unencrypted cfg into encrypted device"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } else { + mxt_info(mxt->ctx, "Device config is unencrypted. Okay to write new config."); + } + } + } + + if (!strncmp(tmp, "MAX_ENCRYPTION_BLOCKS", 21)) { + sscanf(tmp, "%[^'=']=%d", object, &cfg->cfg_blksize); + ignore_line = true; + } + } + continue; } - if (fscanf(fp, "%d", &instance) != 1) { - mxt_err(ctx, "Instance number parse error"); - ret = MXT_ERROR_FILE_FORMAT; - goto close; + /* Found a T68 payload, load parameters into variables */ + if (!strncmp(object, "T68_SERIALDATACOMMAND_PAYLOAD", 29)) { + + if (strstr(object, "ENCRYPTION") != NULL) { + mxt_dbg(mxt->ctx, "Found Encryption payload"); + instance = 0x800C; + } else if (strstr(object, "PWMPATTERN") != NULL) { + mxt_dbg(mxt->ctx, "Found PWM payload"); + instance = 0x800A; + } else if (strstr(object, "SELFCAP_EDGE") != NULL) { + mxt_dbg(mxt->ctx, "Found Edge Shaping payload"); + instance = 0x800B; + } else { + mxt_dbg(mxt->ctx, "Payload datatype unknown"); + ret = MXT_ERROR_BAD_INPUT; + goto close; + } + + while (false == ignore_line) { + if (fscanf(fp, "%s", tmp) != 1) { + mxt_err(mxt->ctx, "Version info header parse error"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + + if (!strncmp(tmp, "PAYLOAD_CHECKSUM", 16)) { + sscanf(tmp, "%[^'=']=%x", object, &payload_crc); + mxt_dbg(mxt->ctx, "Payload_CRC = %x", payload_crc); + } + + if (!strncmp(tmp, "PAYLOAD_SIZE", 12)) { + sscanf(tmp, "%[^'=']=%d", object, &payload_size); + mxt_dbg(mxt->ctx, "Payload_size = %d", payload_size); + skip_addr_size = true; + ignore_line = true; + } + } } - /* Read rest of header section */ - while(c != ']') { - c = getc(fp); - if (c == '\n') { - mxt_err(ctx, "Parse error, expected ] before end of line"); + ignore_line = false; + + if (skip_addr_size != true) { + /* Got object name: Look for Instance num */ + if (fscanf(fp, "%s", tmp) != 1) { + mxt_err(mxt->ctx, "Instance parse error"); ret = MXT_ERROR_FILE_FORMAT; goto close; } - } - while(c != '\n') - c = getc(fp); + if (strcmp(tmp, "INSTANCE")) { + mxt_err(mxt->ctx, "Parse error, expected INSTANCE, got %s", tmp); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } - while ((c != '=') && (c != EOF)) - c = getc(fp); + if (fscanf(fp, "%d", &instance) != 1) { + mxt_err(mxt->ctx, "Instance number parse error"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } - if (fscanf(fp, "%d", &object_address) != 1) { - mxt_err(ctx, "Object address parse error"); - ret = MXT_ERROR_FILE_FORMAT; - goto close; - } + /* Read rest of header section */ + while(c != ']') { + c = getc(fp); + + if (c == '\n') { + mxt_err(mxt->ctx, "Parse error, expected ] before end of line"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + } + + while(c != '\n') + c = getc(fp); + + while ((c != '=') && (c != EOF)) + c = getc(fp); + + if (fscanf(fp, "%d", &object_address) != 1) { + mxt_err(mxt->ctx, "Object address parse error"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } - c = getc(fp); - while((c != '=') && (c != EOF)) c = getc(fp); - if (fscanf(fp, "%d", &object_size) != 1) { - mxt_err(ctx, "Object size parse error"); - ret = MXT_ERROR_FILE_FORMAT; - goto close; - } + while((c != '=') && (c != EOF)) + c = getc(fp); - c = getc(fp); + if (fscanf(fp, "%d", &object_size) != 1) { + mxt_err(mxt->ctx, "Object size parse error"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } - /* Find object type ID number at end of object string */ - substr = strrchr(object, '_'); - if (substr == NULL || (*(substr + 1) != 'T')) { - mxt_err(ctx, "Parse error, could not find T number in %s", object); - ret = MXT_ERROR_FILE_FORMAT; - goto close; - } + c = getc(fp); - if (sscanf(substr + 2, "%d", &object_id) != 1) { - mxt_err(ctx, "Unable to get object type ID for %s", object); - ret = MXT_ERROR_FILE_FORMAT; - goto close; + /* Find object type ID number at end of object string */ + substr = strrchr(object, '_'); + if (substr == NULL || (*(substr + 1) != 'T')) { + mxt_err(mxt->ctx, "Parse error, could not find T number in %s", object); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + + if (sscanf(substr + 2, "%d", &object_id) != 1) { + mxt_err(mxt->ctx, "Unable to get object type ID for %s", object); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + } /* End of skip address size */ + + /* Save T68 data, found, don't do 2nd time */ + if (object_id == 68) { + t68_ctx.t68_object_id = object_id; + t68_ctx.t68_size = object_size; + t68_ctx.t68_instance = instance; + t68_ctx.t68_addr = object_address; } - mxt_dbg(ctx, "%s T%u OBJECT_ADDRESS=%d OBJECT_SIZE=%d", + mxt_dbg(mxt->ctx, "%s T%u OBJECT_ADDRESS=%d OBJECT_SIZE=%d", object, object_id, object_address, object_size); objcfg = calloc(1, sizeof(struct mxt_object_config)); @@ -634,22 +1074,63 @@ static int mxt_load_xcfg_file(struct libmaxtouch_ctx *ctx, const char *filename, goto close; } - objcfg->type = object_id; - objcfg->size = object_size; - objcfg->instance = instance; - objcfg->start_position = object_address; + /* Collect T68 addr, size, instance */ + if (skip_addr_size != true) { + objcfg->type = object_id; + objcfg->instance = instance; + objcfg->start_position = object_address; + objcfg->size = object_size; + + if (CHECK_BIT(mxt->mxt_enc.encryption_state, CFG_ENCRYPTED)) { + + objcfg->enc_size = object_size; + mxt->mxt_enc.enc_datasize = object_size; + add_datasize = true; + + if (object_address > t38_addr) { + /* Padding only needed for CFG enc enabled, not MSG */ + /* Required for xcfg, data is multiples of 16 */ + /* Num of objects requires padding */ + /* TBD - May not need, since .xcfg file content already aligned */ + if ((object_size % 16 == 0x00) && (object_size != 0x00)) { + objcfg->size = object_size; + } else { + /* Adjust size, multiple of 16 if size < 16 bytes*/ + objcfg->size = (16 - (object_size % 16) + object_size); + } + } + /* increase object size overall to 2 for datasize header */ + //objcfg->size += 2; + } /* Add msg enc handling */ + + t68_not = true; + /* TBD need to figure out how to manage MSG enabled */ + /* adds datasize bytes but does not limit blocksize */ + /* Does not need padding */ + } else { + objcfg->type = t68_ctx.t68_object_id; + objcfg->size = payload_size + 4; /* do I need this for xcfg */ + //objcfg->size = payload_size + 2; /* add two for embedded datasize */ + objcfg->instance = instance; + objcfg->start_position = t68_ctx.t68_addr; + skip_addr_size = false; + add_datasize = false; + t68_not = false; + } *next = objcfg; next = &objcfg->next; /* Allocate memory to store configuration */ - objcfg->data = calloc(object_size, sizeof(uint8_t)); + objcfg->data = calloc(objcfg->size + 2, sizeof(uint8_t)); if (!objcfg->data) { - mxt_err(ctx, "Failed to allocate memory"); + mxt_err(mxt->ctx, "Failed to allocate memory"); ret = MXT_ERROR_NO_MEM; goto close; } + int index = 0; + while (true) { int offset; int width; @@ -666,19 +1147,33 @@ static int mxt_load_xcfg_file(struct libmaxtouch_ctx *ctx, const char *filename, break; /* End of file */ - if (c == EOF) + if (c == EOF) { + file_read = true; break; + } /* Read address */ if (fscanf(fp, "%d", &offset) != 1) { - mxt_err(ctx, "Address parse error"); + mxt_err(mxt->ctx, "Address parse error"); ret = MXT_ERROR_FILE_FORMAT; goto close; } + /* Embed the datasize to the content of the configuration */ + if ((CHECK_BIT(mxt->mxt_enc.encryption_state, CFG_ENCRYPTED)) && + (add_datasize == true)) { + /* increase the offset to save two bytes of datasize */ + /* Store at the beginning of data buffer */ + objcfg->data[offset] = objcfg->enc_size & 0x00ff; + objcfg->data[offset + 1] = ((objcfg->enc_size >> 8) & 0x00ff); + + add_datasize = false; + + } /* Add msg encryption handling later */ + /* Read byte count of this register (max 2) */ if (fscanf(fp, "%d", &width) != 1) { - mxt_err(ctx, "Byte count parse error"); + mxt_err(mxt->ctx, "Byte count parse error"); ret = MXT_ERROR_FILE_FORMAT; goto close; } @@ -688,37 +1183,73 @@ static int mxt_load_xcfg_file(struct libmaxtouch_ctx *ctx, const char *filename, } if (fscanf(fp, "%d", &data) != 1) { - mxt_err(ctx, "Data parse error"); + mxt_err(mxt->ctx, "Data parse error"); ret = MXT_ERROR_FILE_FORMAT; goto close; } c = getc(fp); - switch (width) { - case 1: - objcfg->data[offset] = (char) data; - break; - case 2: - objcfg->data[offset] = (char) data & 0xFF; - objcfg->data[offset + 1] = (char) ((data >> 8) & 0xFF); - break; - case 4: - objcfg->data[offset] = (char) data & 0xFF; - objcfg->data[offset + 1] = (char) ((data >> 8) & 0xFF); - objcfg->data[offset + 2] = (char) ((data >> 16) & 0xFF); - objcfg->data[offset + 3] = (char) ((data >> 24) & 0xFF); - break; - default: - mxt_err(ctx, "Only 1, 2 and 4 byte config values are supported"); - ret = MXT_ERROR_FILE_FORMAT; - goto close; - } + if ((CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED)) && (t68_not == true)) { + switch (width) { + case 1: + objcfg->data[2 + index] = (char) data & 0xFF; + index += width; + break; + case 2: + objcfg->data[2 + index] = (char) data & 0xFF; + objcfg->data[2 + index + 1] = (char) ((data >> 8) & 0xFF); + index += width; + break; + case 3: + objcfg->data[2 + index] = (char) data & 0xFF; + objcfg->data[2 + index + 1] = (char) ((data >> 8) & 0xFF); + objcfg->data[2 + index + 2] = (char) ((data >> 16) & 0xFF); + index += width; + break; + case 4: + objcfg->data[2 + index] = (char) data & 0xFF; + objcfg->data[2 + index + 1] = (char) ((data >> 8) & 0xFF); + objcfg->data[2 + index + 2] = (char) ((data >> 16) & 0xFF); + objcfg->data[2 + index + 2] = (char) ((data >> 24) & 0xFF); + index += width; + break; + default: + mxt_err(mxt->ctx, "Only 1, 2, 3 and 4 byte config values are supported"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + } else { + switch (width) { + case 1: + objcfg->data[offset] = (char) data & 0xFF; + break; + case 2: + objcfg->data[offset] = (char) data & 0xFF; + objcfg->data[offset + 1] = (char) ((data >> 8) & 0xFF); + break; + + case 3: + objcfg->data[offset] = (char) data & 0xFF; + objcfg->data[offset + 1] = (char) ((data >> 8) & 0xFF); + objcfg->data[offset + 2] = (char) ((data >> 16) & 0xFF); + break; + case 4: + objcfg->data[offset] = (char) data & 0xFF; + objcfg->data[offset + 1] = (char) ((data >> 8) & 0xFF); + objcfg->data[offset + 2] = (char) ((data >> 16) & 0xFF); + objcfg->data[offset + 3] = (char) ((data >> 24) & 0xFF); + break; + default: + mxt_err(mxt->ctx, "Only 1, 2, 3 and 4 byte config values are supported"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + } } - } - + } ret = MXT_SUCCESS; - mxt_info(ctx, "Configuration read from %s in XCFG format", filename); + mxt_info(mxt->ctx, "Configuration read from %s in XCFG format", filename); close: fclose(fp); @@ -728,12 +1259,14 @@ static int mxt_load_xcfg_file(struct libmaxtouch_ctx *ctx, const char *filename, //****************************************************************************** /// \brief Load configuration from RAW file // \return #mxt_rc -static int mxt_load_raw_file(struct libmaxtouch_ctx *ctx, const char *filename, +static int mxt_load_raw_file(struct mxt_device *mxt, const char *filename, struct mxt_config *cfg) { FILE *fp; int ret; size_t i; + bool t38_found = false; + bool t68_payload_found = false; char line[2048]; struct mxt_object_config **next; struct mxt_object_config *objcfg; @@ -742,27 +1275,86 @@ static int mxt_load_raw_file(struct libmaxtouch_ctx *ctx, const char *filename, fp = fopen(filename, "r"); if (fp == NULL) { - mxt_err(ctx, "Error opening %s: %s", filename, strerror(errno)); + mxt_err(mxt->ctx, "Error opening %s: %s", filename, strerror(errno)); return mxt_errno_to_rc(errno); } if (fgets(line, sizeof(line), fp) == NULL) { - mxt_err(ctx, "Unexpected EOF"); + mxt_err(mxt->ctx, "Unexpected EOF"); } - if (strncmp(line, OBP_RAW_MAGIC, strlen(OBP_RAW_MAGIC))) { - mxt_warn(ctx, "Not in OBP_RAW format"); + if (!strncmp(line, OBP_RAW_MAGIC_V1, strlen(OBP_RAW_MAGIC_V1))) { + mxt_info(mxt->ctx, "Found Version 1 config file"); + } else if (!strncmp(line, OBP_RAW_MAGIC_V2, strlen(OBP_RAW_MAGIC_V2))) { + mxt_info(mxt->ctx, "Found Version 2 config file"); + } else if (!strncmp(line, OBP_RAW_MAGIC_V3, strlen(OBP_RAW_MAGIC_V3))) { + mxt_info(mxt->ctx, "Found Version 3 config file"); + cfg->cfg_version = 0x03; + } else { ret = MXT_ERROR_FILE_FORMAT; + mxt_dbg(mxt->ctx, "Not in OBP_RAW format"); goto close; - } else { - mxt_dbg(ctx, "Loading OBP_RAW file"); + } + + mxt_dbg(mxt->ctx, "Loading OBP_RAW file"); + + if (cfg->cfg_version == 0x03) { + + ret = (fscanf(fp, "%s%d", line, &cfg->cfg_enc)); + if (ret != 2) { + mxt_err(mxt->ctx, "Bad format, ENCRYPTION header not found\n"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + + if (cfg->cfg_enc) { + if (CHECK_BIT(mxt->mxt_enc.encryption_state, CFG_ENCRYPTED)) { + mxt_info(mxt->ctx, "Config and device are encrypted." + " Okay to update chip configuration."); + } else { + mxt_info(mxt->ctx, "Cannot program encrypted cfg into unencrypted device"); + ret = MXT_ERROR_NOT_SUPPORTED; + goto close; + } + } else { + mxt_info(mxt->ctx, "Config file is unencrypted. Checking device encryption"); + + if (CHECK_BIT(mxt->mxt_enc.encryption_state, CFG_ENCRYPTED)) { + mxt_err(mxt->ctx, "Cannot program unencrypted cfg into" + "encrypted device"); + ret = MXT_ERROR_NOT_SUPPORTED; + goto close; + } else { + mxt_info(mxt->ctx, "Device config is unencrypted. Okay to write new config"); + } + } + + if (!strncmp(line, "ENC_HDR", strlen(ENC_HDR))) { + mxt_err(mxt->ctx, "Unexpected header found %s", line); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + + ret = (fscanf(fp, "%s%d", line, &cfg->cfg_blksize)); + if (ret != 2) { + mxt_err(mxt->ctx, "Bad format, ENCRYPTION header not found\n"); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } + + if (!strncmp(line, "ENC_BLOCK_HDR", + strlen(ENC_BLOCK_HDR))) { + mxt_err(mxt->ctx, "Unexpected header found %s", line); + ret = MXT_ERROR_FILE_FORMAT; + goto close; + } } /* Load information block and check */ for (i = 0; i < sizeof(struct mxt_id_info); i++) { ret = fscanf(fp, "%hhx", (unsigned char *)&cfg->id + i); if (ret != 1) { - mxt_err(ctx, "Bad format"); + mxt_err(mxt->ctx, "Bad format"); ret = MXT_ERROR_FILE_FORMAT; goto close; } @@ -771,14 +1363,14 @@ static int mxt_load_raw_file(struct libmaxtouch_ctx *ctx, const char *filename, /* Read CRCs */ ret = fscanf(fp, "%x", &cfg->info_crc); if (ret != 1) { - mxt_err(ctx, "Bad format: failed to parse Info CRC"); + mxt_err(mxt->ctx, "Bad format: failed to parse Info CRC"); ret = MXT_ERROR_FILE_FORMAT; goto close; } ret = fscanf(fp, "%x", &cfg->config_crc); if (ret != 1) { - mxt_err(ctx, "Bad format: failed to parse Config CRC"); + mxt_err(mxt->ctx, "Bad format: failed to parse Config CRC"); ret = MXT_ERROR_FILE_FORMAT; goto close; } @@ -792,51 +1384,92 @@ static int mxt_load_raw_file(struct libmaxtouch_ctx *ctx, const char *filename, goto close; } - /* Read type, instance, length */ - ret = fscanf(fp, "%x %" SCNx8 " %x", + /* Read type,instance,length - Use SCNx16 for T68 payload */ + ret = fscanf(fp, "%x %" SCNx16 " %x", &objcfg->type, &objcfg->instance, &objcfg->size); if (ret == EOF) { free(objcfg); break; } else if (ret != 3) { - mxt_err(ctx, "Bad format: failed to parse object"); + mxt_err(mxt->ctx, "Bad format: failed to parse object"); free(objcfg); ret = MXT_ERROR_FILE_FORMAT; goto close; } - mxt_dbg(ctx, "OBP_RAW T%u instance %u", objcfg->type, objcfg->instance); + if ((objcfg->type == 68) && (objcfg->instance & 0x8000)) { + mxt_info(mxt->ctx, "T68 payload found\n"); + t68_payload_found = true; + } + + if (cfg->cfg_version = 0x03) { + /* Initialize objcfg->enc_size */ + objcfg->enc_size = objcfg->size; + mxt->mxt_enc.enc_datasize = objcfg->size; + + if (objcfg->type == 38) { + t38_found = true; + } + + /* Required for raw, data must be in multiples of 16 for enc */ + /* Object size requires padding */ + + if (t38_found && (t68_payload_found != true)) { + if (cfg->cfg_enc) { + + if (!((objcfg->enc_size % 16 == 0x00) && (objcfg->enc_size != 0x00))) { + objcfg->size = (16 - (objcfg->enc_size % 16) + + objcfg->enc_size); + } + } + } + } /* End of cfg->version */ + + mxt_dbg(mxt->ctx, "OBP_RAW T%u instance %u", objcfg->type, objcfg->instance); *next = objcfg; next = &objcfg->next; - /* Malloc memory to store configuration */ - objcfg->data = calloc(objcfg->size, sizeof(uint8_t)); + /*TBD need to allocate addition 2 bytes for encryption only */ + /* Malloc memory to store configuration and two byte datasize */ + objcfg->data = calloc(objcfg->size + 2, sizeof(uint8_t)); if (!objcfg->data) { - mxt_err(ctx, "Failed to allocate memory"); + mxt_err(mxt->ctx, "Failed to allocate memory"); ret = MXT_ERROR_NO_MEM; goto close; } - /* Read bytes from file */ + if (cfg->cfg_enc && (t68_payload_found != true)) { + objcfg->data[0] = objcfg->enc_size & 0x00ff; + objcfg->data[1] = (objcfg->enc_size >> 8) & 0x00ff; + } + + /* Read bytes from file, load into data buffer*/ for (i = 0; i < objcfg->size; i++) { uint8_t val; ret = fscanf(fp, "%hhx", &val); if (ret != 1) { - mxt_err(ctx, "Parse error in T%d", objcfg->type); + mxt_err(mxt->ctx, "Parse error in T%d", objcfg->type); ret = MXT_ERROR_FILE_FORMAT; free(objcfg->data); goto close; } - *(objcfg->data + i) = val; + if (cfg->cfg_enc && (t68_payload_found != true)) { + objcfg->data[2 + i] = val; + } else { + objcfg->data[i] = val; + } + } - mxt_log_buffer(ctx, LOG_DEBUG, "CFG:", objcfg->data, objcfg->size); - } + t68_payload_found = false; + + mxt_log_buffer(mxt->ctx, LOG_DEBUG, "CFG:", objcfg->data, objcfg->size); + } //End of while {true} loop ret = MXT_SUCCESS; - mxt_info(ctx, "Configuration read from %s in OBP_RAW format", filename); + mxt_info(mxt->ctx, "Config loaded from %s in raw format", filename); close: fclose(fp); @@ -846,25 +1479,25 @@ static int mxt_load_raw_file(struct libmaxtouch_ctx *ctx, const char *filename, //****************************************************************************** /// \brief Get the configuration from file /// \return #mxt_rc -static int mxt_get_config_from_file(struct libmaxtouch_ctx *ctx, - const char *filename, struct mxt_config *cfg) +static int mxt_get_config_from_file(struct mxt_device *mxt, + const char *filename, struct mxt_config *cfg) { int ret; char *extension = strrchr(filename, '.'); if (cfg) { if (extension && !strcmp(extension, ".xcfg")) { - ret = mxt_load_xcfg_file(ctx, filename, cfg); + ret = mxt_load_xcfg_file(mxt, filename, cfg); if (ret) return ret; } else { - ret = mxt_load_raw_file(ctx, filename, cfg); + ret = mxt_load_raw_file(mxt, filename, cfg); if (ret) return ret; } } else { ret = MXT_INTERNAL_ERROR; - mxt_err(ctx, "Config is null"); + mxt_err(mxt->ctx, "Config is null"); } return ret; } @@ -879,36 +1512,71 @@ int mxt_load_config_file(struct mxt_device *mxt, const char *filename) struct mxt_config cfg = {{0}}; int ret; - ret = mxt_get_config_from_file(mxt->ctx, filename, &cfg); + ret = mxt_get_config_from_file(mxt, filename, &cfg); if (ret == MXT_SUCCESS) { + mxt->mxt_enc.enc_cfg_write = true; ret = mxt_write_device_config(mxt, &cfg); mxt_free_config(&cfg); + } else { + mxt_dbg(mxt->ctx, "Error loading file content\n"); + mxt->mxt_enc.enc_cfg_write = false; + goto load_config; } + mxt->mxt_enc.enc_cfg_write = false; + ret = mxt_backup_config(mxt, backup_cmd); if (ret) { mxt_err(mxt->ctx, "Error backing up"); - } else { - mxt_info(mxt->ctx, "Configuration backed up"); + } else { + mxt_info(mxt->ctx, "Configuration backed up"); - ret = mxt_reset_chip(mxt, false, 0); + if (mxt->mxt_enc.msg_enc_enabled) { + ret = mxt_set_irq(mxt, false); + } + + ret = mxt_reset_chip(mxt, false, 0); - if (ret) { - mxt_err(mxt->ctx, "Error resetting"); - } else { - mxt_info(mxt->ctx, "Chip reset"); - } - } + if (ret) { + mxt_err(mxt->ctx, "Error resetting"); + } else { + mxt_info(mxt->ctx, "Chip reset"); + } + } + + ret = mxt_msg_reset(mxt); + if (ret) + mxt_err(mxt->ctx, "Messages did not clear. Interrupt line may be low\n" + "Device reset required\n"); + + ret = mxt_read_info_block (mxt); + if (ret) + mxt_info(mxt->ctx, "Warning: Could not read infoblock"); + + mxt_check_encryption(mxt); + + if (mxt->mxt_enc.msg_enc_enabled) { + ret = mxt_set_irq(mxt, true); + if (ret) + mxt_dbg(mxt->ctx, "debug irq was not set\n"); + } + + ret = mxt_msg_reset(mxt); + if (ret) + mxt_err(mxt->ctx, "Messages did not clear. Interrupt line may be low\n" + "Device reset required\n"); +load_config: + //mxt_free_config(&cfg); return ret; } //****************************************************************************** /// \brief Save configuration to file /// \return #mxt_rc -int mxt_save_config_file(struct mxt_device *mxt, const char *filename) +int mxt_save_config_file(struct mxt_device *mxt, const char *filename, uint8_t format) { int ret; @@ -923,9 +1591,9 @@ int mxt_save_config_file(struct mxt_device *mxt, const char *filename) goto config_done; if (extension && !strcmp(extension, ".xcfg")) - ret = mxt_save_xcfg_file(mxt->ctx, filename, &cfg); + ret = mxt_save_xcfg_file(mxt->ctx, filename, &cfg, format); else - ret = mxt_save_raw_file(mxt->ctx, filename, &cfg); + ret = mxt_save_raw_file(mxt->ctx, filename, &cfg, format); mxt_free_config(&cfg); @@ -978,7 +1646,7 @@ int mxt_zero_config(struct mxt_device *mxt) //****************************************************************************** /// \brief Check the checksum for a given file /// \return #mxt_rc -int mxt_checkcrc(struct libmaxtouch_ctx *ctx, struct mxt_device *mxt, char *filename) +int mxt_checkcrc(struct mxt_device *mxt, char *filename) { int ret; struct mxt_config cfg = {{0}}; @@ -988,7 +1656,7 @@ int mxt_checkcrc(struct libmaxtouch_ctx *ctx, struct mxt_device *mxt, char *file uint16_t end_pos = 0; /* Get the mxt_config and object configurations */ - ret = mxt_get_config_from_file(ctx, filename, &cfg); + ret = mxt_get_config_from_file(mxt, filename, &cfg); if (ret) goto free; @@ -996,7 +1664,7 @@ int mxt_checkcrc(struct libmaxtouch_ctx *ctx, struct mxt_device *mxt, char *file struct mxt_object_config *objcfg = cfg.head; if (mxt == NULL) { if (cfg.config_type == CONFIG_RAW) { - mxt_err(ctx, "RAW config format only supported with chip present"); + mxt_err(mxt->ctx, "RAW config format only supported with chip present"); ret = MXT_ERROR_NO_DEVICE; goto free; } else { @@ -1027,13 +1695,13 @@ int mxt_checkcrc(struct libmaxtouch_ctx *ctx, struct mxt_device *mxt, char *file } } - mxt_verb(ctx, "CRC start_pos:%d end_pos:%d", start_pos, end_pos); + mxt_info(mxt->ctx, "CRC start_pos:%d end_pos:%d", start_pos, end_pos); /* Allocate buffer for CRC calculation */ uint8_t *buffer = (uint8_t *)calloc(end_pos, sizeof(uint8_t)); if (!buffer) { ret = MXT_ERROR_NO_MEM; - mxt_err(ctx, "Could not allocate memory for buffer"); + mxt_err(mxt->ctx, "Could not allocate memory for buffer"); goto free; } @@ -1052,13 +1720,13 @@ int mxt_checkcrc(struct libmaxtouch_ctx *ctx, struct mxt_device *mxt, char *file } uint32_t calc_crc; - ret = mxt_calculate_crc(ctx, &calc_crc, buffer + start_pos, end_pos - start_pos); + ret = mxt_calculate_crc(mxt->ctx, &calc_crc, buffer + start_pos, end_pos - start_pos); if (calc_crc == cfg.config_crc) { - mxt_info(ctx, "File checksum verified: %06X", cfg.config_crc); + mxt_info(mxt->ctx, "File checksum verified: %06X", cfg.config_crc); ret = MXT_SUCCESS; } else { - mxt_err(ctx, "Checksum error: calc=%06X file=%06X", calc_crc, cfg.config_crc); + mxt_err(mxt->ctx, "Checksum error: calc=%06X file=%06X", calc_crc, cfg.config_crc); ret = MXT_ERROR_CHECKSUM_MISMATCH; } diff --git a/src/libmaxtouch/i2c_dev/i2c_dev_device.c b/src/libmaxtouch/i2c_dev/i2c_dev_device.c index b3293287..40bbc447 100644 --- a/src/libmaxtouch/i2c_dev/i2c_dev_device.c +++ b/src/libmaxtouch/i2c_dev/i2c_dev_device.c @@ -41,6 +41,7 @@ struct mxt_conn_info; #include "i2c_dev_device.h" #include "libmaxtouch/libmaxtouch.h" +#include "mxt-app/mxt_app.h" #define I2C_SLAVE_FORCE 0x0706 @@ -64,6 +65,7 @@ int i2c_dev_open(struct mxt_device *mxt) /// \brief Release device void i2c_dev_release(struct mxt_device *mxt) { + /* TBD - Pending */ } //****************************************************************************** @@ -94,75 +96,131 @@ static int open_and_set_slave_address(struct mxt_device *mxt, int *fd_out) } //****************************************************************************** -/// \brief Read register from MXT chip +/// \brief Read register from MXT chip with encryption handling /// \return #mxt_rc int i2c_dev_read_register(struct mxt_device *mxt, unsigned char *buf, int start_register, int count, size_t *bytes_read) { int fd = -ENODEV; - char register_buf[4]; + unsigned char *readbuf; + unsigned char *databuf; uint8_t tx_header = 0x04; uint8_t crc_data = 0; - uint8_t tx_value = 0; + int bytesToRead = 0; + uint16_t bytesRead = 0; uint16_t tx_seq_num; + uint16_t msg_length = 0; + size_t w_hdr_size = 0; + uint16_t databuf_size = 0; + char reg_buf[4]; int ret, err; - int i, j; + int i; + + /* Make copy of bytes to read */ + bytesToRead = count; /* Total bytes to read */ + msg_length = count; /* Message length will get modified */ + + /* Modify msg_length */ + if (CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED) && + (start_register != 0x0000) && + (start_register > mxt->mxt_dev.t38_addr + mxt->mxt_dev.t38_size)) { + + if (count > mxt->mxt_enc.enc_blocksize) { + msg_length = mxt->mxt_enc.enc_blocksize; + } else if (count < 16) { + /* Must to be multiple of 16 bytes to read if less than */ + msg_length = 16; + } else if ((count % 16 != 0) && (count != 0)) { + /* Adjust size, multiple of 16 if size < 16 bytes*/ + msg_length = (16 - (count % 16) + count); + } + } else { + /* Limit buffer to 255 */ + if (count > mxt->ctx->i2c_block_size) { + msg_length = mxt->ctx->i2c_block_size; + } + } - if (count > mxt->ctx->i2c_block_size) - count = mxt->ctx->i2c_block_size; + /* Allocate databuf based on which is larger */ + databuf_size = MAX(bytesToRead, msg_length); + + /* Must allocate based on msg_length modification */ + /* readbuf holds data read from the chip */ + + /* modified msg_length */ + readbuf = calloc((msg_length + 1), sizeof(unsigned char)); + if (!readbuf) { + ret = MXT_ERROR_NO_MEM; + goto close; + } + + databuf = calloc((databuf_size + 1), sizeof(unsigned char)); + if (!databuf) { + ret = MXT_ERROR_NO_MEM; + goto close_readbuf; + } ret = open_and_set_slave_address(mxt, &fd); if (ret) return ret; + + /* Normal and encrypted writes, add datasize*/ + if (mxt->mxt_crc.crc_enabled != true) { - if (mxt->mxt_crc.crc_enabled == false) { - - register_buf[0] = start_register & 0xff; - register_buf[1] = (start_register >> 8) & 0xff; + reg_buf[0] = start_register & 0xff; + reg_buf[1] = (start_register >> 8) & 0xff; + + w_hdr_size = 2; /* Default datasize, chip not enc */ + + /* datasize is required to be zero if only changing */ + /* write address before read */ + if (CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED)) { + reg_buf[2] = 0x00; + reg_buf[3] = 0x00; + w_hdr_size = 4; /* update header size, incl datasize */ + } - if (write(fd, ®ister_buf, 2) != 2) { + if (write(fd, ®_buf, w_hdr_size) != w_hdr_size) { mxt_verb(mxt->ctx, "I2C retry"); usleep(I2C_RETRY_DELAY); - if (write(fd, ®ister_buf, 2) != 2) { + if (write(fd, ®_buf, w_hdr_size) != w_hdr_size) { mxt_err(mxt->ctx, "Error %s (%d) writing to i2c", strerror(errno), errno); ret = mxt_errno_to_rc(errno); - goto close; + goto close_databuf; } } - } else { + } else { /* HA reads */ if (mxt->debug_fs.enabled == true) { + err = debugfs_set_irq(mxt, false); - if (err) mxt_dbg(mxt->ctx, "Could not disable IRQ"); err = debugfs_get_tx_seq_num(mxt, &tx_seq_num); - - if (err) { + if (err) mxt_dbg(mxt->ctx, "Failed to get the tx seq num"); - } } - register_buf[0] = start_register & 0xff; - register_buf[1] = (start_register >> 8) & 0xff; - register_buf[2] = tx_seq_num; //Must be tx seq no + reg_buf[0] = start_register & 0xff; + reg_buf[1] = (start_register >> 8) & 0xff; + reg_buf[2] = tx_seq_num; - //Calculate CRC byte + /* Calculate CRC byte */ for (i = 0; i < (tx_header - 1); i++) { - crc_data = mxt_calc_crc8(crc_data, register_buf[i]); + crc_data = mxt_calc_crc8(crc_data, reg_buf[i]); } - register_buf[3] = crc_data; //CRC8 bit checksum + reg_buf[3] = crc_data; /* CRC8 bit checksum */ - if (write(fd, ®ister_buf, 4) != 4) { + if (write(fd, ®_buf, 4) != 4) { mxt_verb(mxt->ctx, "I2C retry"); usleep(I2C_RETRY_DELAY); - if (write(fd, ®ister_buf, 4) != 4) { + if (write(fd, ®_buf, 4) != 4) { mxt_err(mxt->ctx, "Error %s (%d) writing to i2c", strerror(errno), errno); ret = mxt_errno_to_rc(errno); - goto close; + goto close_databuf; } } @@ -170,25 +228,65 @@ int i2c_dev_read_register(struct mxt_device *mxt, unsigned char *buf, if (err) { mxt_dbg(mxt->ctx, "Failed to get the tx seq num"); - goto close; + goto close_databuf; } - } + } /* Finish HA reads */ ssize_t read_rc; - read_rc = read(fd, buf, count); - if (read_rc < 0) { + read_rc = read(fd, readbuf, msg_length); + if (read_rc < 0) { mxt_err(mxt->ctx, "Error %s (%d) reading from i2c", strerror(errno), errno); ret = mxt_errno_to_rc(errno); - goto close; + goto close_databuf; + } else if (read_rc == 0) { /* end of file */ ret = MXT_ERROR_IO; - goto close; - } else { - *bytes_read = (size_t)read_rc; - ret = MXT_SUCCESS; + goto close_databuf; + } else { /* Process the read */ + + /* Decrpyt if needed */ + + if (CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED) && + (start_register > mxt->mxt_dev.t38_addr + mxt->mxt_dev.t38_size)) { + + /* Pending - Decipher handling not yet available */ + + } + + memcpy(&databuf[bytesRead], &readbuf[0], msg_length); + + bytesRead += msg_length; + *bytes_read = (size_t)bytesRead; + bytesToRead -= msg_length; + + if (CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED) && + (start_register != 0x0000) && + (start_register > mxt->mxt_dev.t38_addr + mxt->mxt_dev.t38_size)) { + + if (bytesToRead < 16 && bytesToRead != 0) { + msg_length = 16; + } else { + msg_length = bytesToRead; + } + } else { + /* Encrypted or not, do not adjust for infoblock read */ + msg_length = bytesToRead; + } } + memcpy(buf, databuf, count); + + ret = MXT_SUCCESS; + +close_databuf: + free(databuf); + databuf = NULL; + +close_readbuf: + free(readbuf); + readbuf = NULL; + close: close(fd); return ret; @@ -201,29 +299,26 @@ int i2c_dev_write_crc(struct mxt_device *mxt, unsigned char const *val, int start_register, size_t datalength) { int fd = -ENODEV; - int count; - int ret, err, i, j; uint16_t msg_count; unsigned char *buf; uint8_t msgbuf[15]; uint16_t tx_seq_num; - uint8_t txbuf[4]; uint8_t tx_header = 4; uint8_t crc_data = 0; uint16_t bytesToWrite = 0; uint16_t message_length = 0; - uint8_t max_data_length = 11; + uint8_t max_length = 11; uint16_t write_addr = 0; uint16_t bytesWritten = 0; uint16_t retry_counter = 0; + int ret, err, i, j; + int count; err = debugfs_set_irq(mxt, false); - if (err) mxt_dbg(mxt->ctx, "Could not disable IRQ"); err = debugfs_get_tx_seq_num(mxt, &tx_seq_num); - if (err) { mxt_dbg(mxt->ctx, "i2c-dev: Failed to get the tx seq num"); } @@ -232,13 +327,13 @@ int i2c_dev_write_crc(struct mxt_device *mxt, unsigned char const *val, if (ret) return ret; - count = datalength + 2; //Total bytes + header - bytesToWrite = datalength; //Total bytes + count = datalength + 2; /* Total bytes + header */ + bytesToWrite = datalength; /* Total bytes */ - //Limit the size for HA parts + /* Limit the size for HA parts */ - if (datalength > max_data_length) { - message_length = max_data_length; + if (datalength > max_length) { + message_length = max_length; } else { message_length = datalength; } @@ -247,8 +342,10 @@ int i2c_dev_write_crc(struct mxt_device *mxt, unsigned char const *val, buf = (unsigned char *)calloc(count, sizeof(unsigned char)); - if (!(datalength == 0x00)) //Prevent memory crash - memcpy(buf, val, datalength); + /* Prevent memory crash */ + if (!(datalength == 0x00)) { + memcpy(buf, val, datalength); + } do { @@ -269,14 +366,15 @@ int i2c_dev_write_crc(struct mxt_device *mxt, unsigned char const *val, crc_data = 0; - //Calculate CRC byte + /* Calculate CRC byte */ for (i = 0; i < (msg_count - 1); i++) { crc_data = mxt_calc_crc8(crc_data, msgbuf[i]); mxt_dbg(mxt->ctx, "Write CRC: Data[%d] = %x, crc = 0x%x\n", i, msgbuf[i], crc_data); } - msgbuf[msg_count - 1] = crc_data; //Insert CRC, end of message + /* Insert CRC, end of message */ + msgbuf[msg_count - 1] = crc_data; ret = write(fd, msgbuf, msg_count); @@ -304,32 +402,32 @@ int i2c_dev_write_crc(struct mxt_device *mxt, unsigned char const *val, if (retry_counter == 10) break; -} while (bytesToWrite > 0); + } while (bytesToWrite > 0); tx_seq_num--; //Minus 1 before updating ret = debugfs_update_seq_num(mxt, (uint8_t) tx_seq_num); if ((mxt->mxt_crc.reset_triggered == false) && (mxt->mxt_crc.config_triggered == false) && - mxt->mxt_crc.processing_msg == false){ + mxt->mxt_crc.processing_msg == false) { err = debugfs_set_irq(mxt, true); - - if (err) + if (err) mxt_dbg(mxt->ctx, "Could not disable IRQ"); -} + } + buf = NULL; free(buf); close(fd); return ret; } - //****************************************************************************** /// \brief Write register to MXT chip /// \return #mxt_rc -int i2c_dev_write_register(struct mxt_device *mxt, unsigned char const *val, +/// No longer in use +int i2c_dev_write_reg(struct mxt_device *mxt, unsigned char const *val, int start_register, size_t datalength) { int fd = -ENODEV; @@ -361,11 +459,192 @@ int i2c_dev_write_register(struct mxt_device *mxt, unsigned char const *val, ret = MXT_SUCCESS; } + buf = NULL; free(buf); close(fd); return ret; } +//****************************************************************************** +/// \brief Write register to MXT chip +/// \return #mxt_rc +int i2c_dev_write_register(struct mxt_device *mxt, unsigned char const *val, + int start_register, size_t datalength) +{ + int fd = -ENODEV; + int ret, i; + unsigned char *abuf; + unsigned char tbuf[1024]; + uint16_t enc_datasize = 0; + uint16_t data_size = 0; + int bytesToWrite = 0; + uint16_t msg_length = 0; + uint16_t bytesWritten = 0; + uint16_t write_addr = 0; + uint8_t retry_counter = 0; + size_t msg_count; + uint16_t write_offset = 0; + uint16_t tmp_length = 0; + uint8_t tmp_padding = 0; + uint8_t wr_offset = 0; + uint8_t temp = 0; + + ret = open_and_set_slave_address(mxt, &fd); + if (ret) + return ret; + + mxt_dbg(mxt->ctx, "%s start_register:%d datalength:%zu", __func__, + start_register, datalength); + + /* Determine msg_length and # of bytes to write */ + if (CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED)) { + if ((mxt->mxt_enc.encryption_state & CFG_DEV_MASK) == CFG_DEV_MASK) { + /* Writes of config file content with embedded data size header bytes */ + if (mxt->mxt_enc.enc_cfg_write == true) { + msg_length = datalength - 2; + bytesToWrite = datalength - 2; + } else { /* TBD, write from mxt-app when encrypted, need datasize byte */ + msg_length = datalength; + bytesToWrite = datalength; + enc_datasize = msg_length; + } + } + } else { /* Normal writes with no encryption, no datasize */ + msg_length = datalength; + bytesToWrite = datalength; + } + + /* Limit the number of bytes to block size if encrypted */ + if (CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED) && + (mxt->mxt_enc.enc_cfg_write == true)) { + + /* buffer embedded datasize bytes */ + enc_datasize = (((val[1] >> 8) & 0xff00) | (val[0] & 0xff)); + memcpy(&tbuf[0], &val[2], bytesToWrite); + + /* Limit or pad msg_length if device is encrypted */ + if (msg_length > mxt->mxt_enc.enc_blocksize) { + msg_length = mxt->mxt_enc.enc_blocksize; + } + + } else if (((mxt->mxt_enc.encryption_state & CFG_DEV_MASK) == CFG_DEV_MASK) && + (start_register > mxt->mxt_dev.t38_addr + mxt->mxt_dev.t38_size)) { + /* Determine how much padding is needed*/ + tmp_length = msg_length; + + if (!((msg_length % 16 == 0x00) && (msg_length != 0x00))) { + msg_length = (16 - (msg_length % 16) + msg_length); + bytesToWrite = msg_length; /* update the msg_length */ + } + + /* Padding bytes needed */ + tmp_padding = (msg_length - tmp_length); + + /* Copy data to tbuf, original size no padding*/ + memcpy(&tbuf[0], &val[0], tmp_length); + + /* Copy random byte to buffer */ + tbuf[tmp_length] = mxt->mxt_enc.renc_byte; + tmp_padding -= 1; + + wr_offset = tmp_length + 1; /* Inc 1 byte padding */ + + while (tmp_padding > 0) { + /* tmp_padding is 8 */ + + temp = MIN(tmp_padding, datalength); + + memcpy(&tbuf[wr_offset], &val[0], temp); + + /* Reduce tmp_padding by how much we added */ + tmp_padding -= temp; + /* Adjust write offset */ + wr_offset += temp; + } + + /* Pending - Cipher code not yet available */ + + } else { /* Normal write with no encryption */ + memcpy(&tbuf[0], &val[0], bytesToWrite); + } + + /* Add 4 for datasize and reg address */ + abuf = (unsigned char *)calloc((msg_length + 4), sizeof(unsigned char)); + if (!abuf) + return MXT_ERROR_NO_MEM; + + do { + + write_addr = start_register + bytesWritten; + + abuf[0] = write_addr & 0xff; + abuf[1] = (write_addr >> 8) & 0xff; + + if (CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED)) { + if ((mxt->mxt_enc.encryption_state & CFG_DEV_MASK) == CFG_DEV_MASK) { + if (write_addr >= ((mxt->mxt_dev.t38_addr + mxt->mxt_dev.t38_size))) { + if (enc_datasize < mxt->mxt_enc.enc_blocksize) { + data_size = enc_datasize; + } else { + data_size = mxt->mxt_enc.enc_blocksize; + } + } else { + data_size = 0x0000; + } + + abuf[2] = data_size & 0xff; + abuf[3] = (data_size >> 8) & 0xff; + + msg_count = msg_length + 4; + + /* Copy all data to buf after addr and datasize bytes */ + /* write offset use to skip embedded datasize */ + memcpy(&abuf[4], (tbuf + bytesWritten), msg_length); + + } else { + /* Datasize on write set to 0x0000 when Msg Enc On */ + abuf[2] = 0x00; + abuf[3] = 0x00; + } + } else { + msg_count = msg_length + 2; + memcpy(&abuf[2], (tbuf + bytesWritten), msg_length); + } + + ret = write(fd, abuf, msg_count); + + if (ret == msg_count) { + ret = MXT_SUCCESS; + bytesWritten += msg_length; + bytesToWrite -= msg_length; + enc_datasize -= msg_length; + + if (bytesToWrite < msg_length) { + msg_length = bytesToWrite; + } + + retry_counter = 0; + + } else { + mxt_warn(mxt->ctx, "Warning error %s, (%d) occurred while writing to i2c. Retrying", + strerror(errno), errno); + retry_counter++; + usleep(I2C_RETRY_DELAY); + } + + if (retry_counter == 3) { + mxt_err(mxt->ctx, "Error %s, (%d) writing to i2c", strerror(errno), errno); + break; + } + + } while (bytesToWrite > 0); + + free(abuf); + abuf = NULL; + close(fd); + return ret; +} + //****************************************************************************** /// \brief Bootloader read /// \return #mxt_rc @@ -419,4 +698,4 @@ int i2c_dev_bootloader_write(struct mxt_device *mxt, unsigned char const *buf, *bytes_read = count; close(fd); return ret; -} +} \ No newline at end of file diff --git a/src/libmaxtouch/i2c_dev/i2c_dev_device.h b/src/libmaxtouch/i2c_dev/i2c_dev_device.h index 4ac090e0..a6bf99ac 100644 --- a/src/libmaxtouch/i2c_dev/i2c_dev_device.h +++ b/src/libmaxtouch/i2c_dev/i2c_dev_device.h @@ -28,6 +28,11 @@ // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //------------------------------------------------------------------------------ +#include +#include +#include +#include + #define I2C_DEV_MAX_BLOCK 255 //****************************************************************************** @@ -38,8 +43,10 @@ struct i2c_dev_conn_info { }; //****************************************************************************** -/// \brief Device information for i2c-dev backend +/// \brief Device parameter for i2c-dev usage struct i2c_dev_device { + uint16_t t38_addr; + uint16_t t38_size; }; int i2c_dev_open(struct mxt_device *mxt); diff --git a/src/libmaxtouch/info_block.c b/src/libmaxtouch/info_block.c index 37dff096..d34ac8e9 100644 --- a/src/libmaxtouch/info_block.c +++ b/src/libmaxtouch/info_block.c @@ -96,6 +96,93 @@ int mxt_calculate_crc(struct libmaxtouch_ctx *ctx, uint32_t *crc_result, return MXT_SUCCESS; } +static bool mxt_lookup_chips(struct mxt_device *mxt) +{ + struct mxt_id_info *id = mxt->info.id; + uint8_t family_id; + uint8_t variant_id; + bool is_chip_found = false; + + family_id = id->family; + variant_id = id->variant; + + switch (family_id) { + case 0xA4: + + if (variant_id & 0x80) { + SET_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED); + mxt_info(mxt->ctx, "Device is encrypted\n"); + } + + is_chip_found = true; + + switch (variant_id & 0x80) { + + case 0x3D: //"1067TDAT" + mxt_info(mxt->ctx, "Found mXT1067DAT"); + break; + case 0x3E: //"2113TDAT" + mxt_info(mxt->ctx, "Found mXT2113TDAT"); + break; + case 0x3F: //"2113TGAT" + mxt_info(mxt->ctx, "Found mXT2113TGAT"); + break; + case 0x42: //"2952TD" + mxt_info(mxt->ctx, "Found mXT2952TD-002"); + break; + + default: + mxt_info(mxt->ctx, "Found maXTouch device"); + break; + + } + + break; + + case 0xA6: + + if (variant_id & 0x80) { + SET_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED); + mxt_dbg(mxt->ctx, "Device is encrypted\n"); + mxt->mxt_enc.enc_blocksize = 0x30; + } else { + CLEAR_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED); + mxt_dbg(mxt->ctx, "Device is unencrypted\n"); + } + + is_chip_found = true; + + switch (variant_id & 0x80) { + case 0x14: //"336UD-HA" + mxt_info(mxt->ctx, "Found mXT366UD-HA\n"); + break; + case 0x15: //"640UD-HA" + mxt_info(mxt->ctx, "Found mXT640UD-HA\n"); + break; + case 0x16: //"448UD-HA" + mxt_info(mxt->ctx, "Found mXT448UD-HA\n"); + break; + case 0x1C: //"336UD-002" + mxt_info(mxt->ctx, "Found mXT336UD-002\n"); + break; + case 0x1D: //"228UD-002" + mxt_info(mxt->ctx, "Found mXT288UD-002\n"); + break; + + default: + mxt_info(mxt->ctx, "Found maXTouch device\n"); + break; + } + + break; + + default: + break; + } + + return is_chip_found; +} + /*! * @brief Reads the information block from the chip. * @return #mxt_rc @@ -115,7 +202,7 @@ int mxt_read_info_block(struct mxt_device *mxt) } if (mxt->conn->type == E_I2C_DEV) { - + /* Only doing this for i2c_dev */ ret = debugfs_scan(mxt); if (ret == MXT_SUCCESS) { @@ -128,7 +215,7 @@ int mxt_read_info_block(struct mxt_device *mxt) ret = debugfs_get_crc_enabled(mxt, &crc_flag); if (ret) - mxt_err(mxt->ctx, "Could not get crc_enabled flag"); + mxt_err(mxt->ctx, "debugfs: Could not get crc_enable flag"); if (crc_flag) mxt->mxt_crc.crc_enabled = true; @@ -139,6 +226,7 @@ int mxt_read_info_block(struct mxt_device *mxt) } } + /* read first 7 bytes of infoblock */ ret = mxt_read_register(mxt, info_blk, 0, sizeof(struct mxt_id_info)); if (ret) { mxt_err(mxt->ctx, "Failed to read ID information"); @@ -193,6 +281,9 @@ int mxt_read_info_block(struct mxt_device *mxt) return MXT_ERROR_CHECKSUM_MISMATCH; } + if (!(mxt_lookup_chips(mxt))) + mxt_dbg(mxt->ctx, "Unrecognised device\n"); + mxt_dbg(mxt->ctx, "Info checksum verified %06X", calc_crc); return MXT_SUCCESS; } @@ -303,6 +394,30 @@ void mxt_display_chip_info(struct mxt_device *mxt) } else{ mxt->mxt_crc.crc_enabled = true; } + + mxt->mxt_dev.t38_addr = mxt_get_object_address(mxt, SPT_USERDATA_T38, 0); + + if (mxt->mxt_dev.t38_addr == OBJECT_NOT_FOUND) { + mxt_info(mxt->ctx, "T38 Object not Found\n"); + } else { + mxt->mxt_dev.t38_size = mxt_get_object_size(mxt, SPT_USERDATA_T38); + } + + switch (id->family) { + case 0xA6: + if (id->variant & 0x80) { + SET_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED); + mxt_info(mxt->ctx, "mxt-app: Device is encrypted\n"); + mxt->mxt_enc.enc_blocksize = 0x30; + } else { + CLEAR_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED); + } + + break; + + default: + break; + } } /*! diff --git a/src/libmaxtouch/info_block.h b/src/libmaxtouch/info_block.h index 94fd9a12..5d1f0da9 100644 --- a/src/libmaxtouch/info_block.h +++ b/src/libmaxtouch/info_block.h @@ -37,6 +37,25 @@ struct libmaxtouch_ctx; #define MXT_SIZE(o) ((uint16_t)((o).size_minus_one) + 1) #define MXT_OBJECT_SIZE_MAX 256 +/* Define macros */ +#define CHECK_BIT(var, pos) (((unsigned int)(var) >> (pos)) & 1) +#define SET_BIT(var, pos) (var |= (1U << pos)) +#define CLEAR_BIT(var, pos) (var &= (~(1U<< pos))) + +/* T2 status bits */ +#define CONFIGENCEN 0x02 +#define MSGENCEN 0x04 + +/* T2 object offsets */ +#define T2_PAYLOADCRC_OFFSET 0x02 +#define T2_ENCKEYCRC_OFFSET 0x05 + +/* Bit position, use with check, set and clear bit macros */ +#define CFG_ENCRYPTED 0x00 +#define DEV_ENCRYPTED 0x01 +#define MSG_ENCRYPTED 0x02 +#define CFG_DEV_MASK 0x03 + /*! \brief Checksum element struct */ struct mxt_raw_crc { /*! CRC field */ @@ -123,6 +142,21 @@ struct mxt_report_id_map { uint8_t instance; /*!< Instance number */ }; +//****************************************************************************** +/// \brief T2 Encryption Context object +struct mxt_enc_device { + uint16_t addr; + uint8_t enc_blocksize; + uint32_t enc_payloadcrc; + uint32_t enc_custkeycrc; + uint8_t encryption_state; + uint8_t enc_datasize; + uint8_t error_status; + bool msg_enc_enabled; + bool enc_cfg_write; + uint8_t renc_byte; +}; + /*! Object types */ #define F_ENUM(x, y) x = y, #define F_SWITCH(x, y) case x: return ( #x ); @@ -130,7 +164,7 @@ struct mxt_report_id_map { #define OBJECT_LIST(f) \ f(RESERVED_T0, 0) \ f(RESERVED_T1, 1) \ - f(DEBUG_DELTAS_T2, 2) \ + f(GEN_ENCRYPTIONSTATUS_T2, 2) \ f(DEBUG_REFERENCES_T3, 3) \ f(DEBUG_SIGNALS_T4, 4) \ f(GEN_MESSAGEPROCESSOR_T5, 5) \ diff --git a/src/libmaxtouch/libmaxtouch.c b/src/libmaxtouch/libmaxtouch.c index 6d75c349..95e85191 100644 --- a/src/libmaxtouch/libmaxtouch.c +++ b/src/libmaxtouch/libmaxtouch.c @@ -270,6 +270,8 @@ int mxt_get_info(struct mxt_device *mxt) if (ret) return ret; + //mxt_print_info_block(mxt); + ret = mxt_calc_report_ids(mxt); if (ret) { mxt_err(mxt->ctx, "Failed to generate report ID look-up table"); @@ -278,6 +280,11 @@ int mxt_get_info(struct mxt_device *mxt) mxt_display_chip_info(mxt); + ret = mxt_check_encryption(mxt); + if (ret) { + mxt_dbg(mxt->ctx, "Failed to get encryption status"); + } + return MXT_SUCCESS; } @@ -456,7 +463,7 @@ int mxt_write_register(struct mxt_device *mxt, uint8_t const *buf, mxt_dbg(mxt->ctx, "Failed to disable debug_irq"); } - ret = sysfs_write_register(mxt, buf, start_register, count); + ret = sysfs_write_register(mxt, buf, start_register, count, 0x00); if (mxt->mxt_crc.crc_enabled == true) { if (mxt->mxt_crc.reset_triggered == false) { @@ -511,7 +518,7 @@ int mxt_write_bytes(struct mxt_device *mxt, uint8_t const *buf, switch (mxt->conn->type) { case E_SYSFS_SPI: case E_SYSFS_I2C: - ret = sysfs_write_register(mxt, buf, start_register, count); + ret = sysfs_write_register(mxt, buf, start_register, count, 0x00); break; case E_I2C_DEV: @@ -856,10 +863,8 @@ int mxt_backup_config(struct mxt_device *mxt, uint8_t backup_command) return MXT_ERROR_OBJECT_NOT_FOUND; /* Write to command processor register to perform command */ - ret = mxt_write_register - ( - mxt, &backup_command, t6_addr + MXT_T6_BACKUPNV_OFFSET, 1 - ); + ret = mxt_write_register(mxt, &backup_command, + t6_addr + MXT_T6_BACKUPNV_OFFSET, 1); if (ret == MXT_SUCCESS) mxt_info(mxt->ctx, "Backed up settings to the non-volatile memory"); @@ -884,10 +889,8 @@ int mxt_report_all(struct mxt_device *mxt) return MXT_ERROR_OBJECT_NOT_FOUND; /* Write to command processor register to perform command */ - ret = mxt_write_register - ( - mxt, &report_all_cmd, t6_addr + MXT_T6_REPORTALL_OFFSET, 1 - ); + ret = mxt_write_register(mxt, &report_all_cmd, + t6_addr + MXT_T6_REPORTALL_OFFSET, 1); if (ret == MXT_SUCCESS) mxt_info(mxt->ctx, "REPORTALL command issued"); @@ -1186,3 +1189,39 @@ int mxt_errno_to_rc(int errno_in) return MXT_ERROR_IO; } } + +//****************************************************************************** +/// \brief Disable driver IRQ based on interface +/// \return #mxt_rc +int mxt_set_irq(struct mxt_device *mxt, bool irq_enabled) +{ + + int ret = 0; + + switch (mxt->conn->type) { +#ifdef HAVE_LIBUSB + case E_USB: + /* TBD */ + break; +#endif /* HAVE_LIBUSB */ + + case E_SYSFS_SPI: + /* TBD */ + break; + + case E_I2C_DEV: + ret = debugfs_set_irq(mxt, irq_enabled); + break; + + case E_SYSFS_I2C: + ret = sysfs_set_debug_irq(mxt, irq_enabled); + break; + + default: + mxt_err(mxt->ctx, "Device type not supported"); + ret = MXT_ERROR_NOT_SUPPORTED; + break; + } + + return ret; +} \ No newline at end of file diff --git a/src/libmaxtouch/libmaxtouch.h b/src/libmaxtouch/libmaxtouch.h index f7a411d4..120b80b9 100644 --- a/src/libmaxtouch/libmaxtouch.h +++ b/src/libmaxtouch/libmaxtouch.h @@ -45,6 +45,7 @@ struct mxt_conn_info; #include "sysfs/sysfs_device.h" #include "debugfs/debugfs_device.h" #include "i2c_dev/i2c_dev_device.h" +#include "../mxt-app/mxt_app.h" #ifdef HAVE_LIBUSB #include "usb/usb_device.h" @@ -80,6 +81,7 @@ struct mxt_conn_info; #define RESET_COMMAND 0x01 #define BOOTLOADER_COMMAND 0xA5 #define BACKUPNV_COMMAND 0x55 +#define RESTORENV_COMMAND 0x33 #define CALIBRATE_COMMAND 0x01 /* Prefix for T5 messages */ @@ -200,14 +202,15 @@ struct mxt_device { struct mxt_report_id_map *report_id_map; char msg_string[255]; struct mxt_crc_device mxt_crc; - + struct mxt_enc_device mxt_enc; + struct i2c_dev_device mxt_dev; union { struct sysfs_device sysfs; struct debugfs_device debug_fs; #ifdef HAVE_LIBUSB struct usb_device usb; #endif - struct i2c_dev_device i2c_dev; + //struct i2c_dev_device i2c_dev; }; }; @@ -237,7 +240,7 @@ int mxt_reset_chip(struct mxt_device *mxt, bool bootloader_mode, uint16_t reset_ int mxt_calibrate_chip(struct mxt_device *mxt); int mxt_backup_config(struct mxt_device *mxt, uint8_t backup_command); int mxt_load_config_file(struct mxt_device *mxt, const char *cfg_file); -int mxt_save_config_file(struct mxt_device *mxt, const char *filename); +int mxt_save_config_file(struct mxt_device *mxt, const char *filename, uint8_t format); int mxt_zero_config(struct mxt_device *mxt); int mxt_get_msg_count(struct mxt_device *mxt, int *count); char *mxt_get_msg_string(struct mxt_device *mxt); @@ -250,7 +253,9 @@ int mxt_bootloader_write(struct mxt_device *mxt, unsigned char const *buf, int c int mxt_msg_wait(struct mxt_device *mxt, int timeout_ms); int mxt_errno_to_rc(int errno_in); int mxt_report_all(struct mxt_device *mxt); -int mxt_checkcrc(struct libmaxtouch_ctx *ctx, struct mxt_device *mxt, char *filename); +int mxt_checkcrc(struct mxt_device *mxt, char *filename); +int mxt_check_encryption(struct mxt_device *mxt); +int mxt_set_irq(struct mxt_device *mxt, bool irq_enabled); #ifdef __cplusplus } diff --git a/src/libmaxtouch/sysfs/sysfs_device.c b/src/libmaxtouch/sysfs/sysfs_device.c index 8be2ff7e..9fb20641 100644 --- a/src/libmaxtouch/sysfs/sysfs_device.c +++ b/src/libmaxtouch/sysfs/sysfs_device.c @@ -371,7 +371,7 @@ int sysfs_open_i2c(struct mxt_device *mxt) mxt->sysfs.debug_v2 = true; } - mxt_info(mxt->ctx, "\nDevice registered on sysfs path:%s", conn->path); + mxt_info(mxt->ctx, "\nDevice registered on sysfs path:%s\n", conn->path); return MXT_SUCCESS; } @@ -417,7 +417,7 @@ int sysfs_open_spi(struct mxt_device *mxt) mxt->sysfs.debug_v2 = true; } - mxt_info(mxt->ctx, "\nDevice registered on sysfs path:%s", conn->path); + mxt_info(mxt->ctx, "\nDevice registered on sysfs path:%s\n", conn->path); return MXT_SUCCESS; } @@ -485,7 +485,7 @@ int sysfs_bootloader_write(struct mxt_device *mxt, unsigned const char *buf, int ret; size_t *bytes; - ret = sysfs_write_register(mxt, buf, 0x0000, count); + ret = sysfs_write_register(mxt, buf, 0x0000, count, 0x00); return ret; @@ -546,25 +546,166 @@ if ((start_register & 0xffff) != 0x0000) { /// \brief Write register to MXT chip /// \return #mxt_rc int sysfs_write_register(struct mxt_device *mxt, unsigned char const *buf, - int start_register, size_t count) + int start_register, size_t count, size_t padding) { + unsigned char tbuf[1024]; + unsigned char *ebuf; + uint16_t datasize; + uint16_t bytesToWrite = 0; + size_t bytes_written = 0; + uint16_t msg_length = 0; + uint16_t msg_count = 0; + uint8_t tmp_padding = 0; + uint8_t padding_ofs = 0; + uint8_t temp = 0; + uint8_t data_ofs = 0; int fd = -ENODEV; int ret; - size_t bytes_written; + int i; + + /* Make copies original length */ + bytesToWrite = count; + msg_length = count; ret = open_device_file(mxt, &fd); if (ret) return ret; + /* Set write address */ if (lseek(fd, start_register, 0) < 0) { mxt_err(mxt->ctx, "lseek error %s (%d)", strerror(errno), errno); ret = mxt_errno_to_rc(errno); goto close; } + /* Check if encrypted and if not encrypted cfg write */ + /* Logic handles encrypted cfg write, differently */ + if ((CHECK_BIT(mxt->mxt_enc.encryption_state, CFG_ENCRYPTED)) + && (mxt->mxt_enc.enc_cfg_write == false)) { + if (start_register >= ((mxt->mxt_dev.t38_addr + mxt->mxt_dev.t38_size))) { + /* set datasize to incoming count */ + datasize = count; + + /* Determine if count is multiple of 16, find bytesTowrite */ + if (((count % 16) != 0) && (count != 0)) { + msg_length = (16 - (count % 16) + count); /* length with padding */ + bytesToWrite = msg_length; + tmp_padding = msg_length - count; /* exact padding needed */ + } + + ebuf = (unsigned char *)calloc((msg_length + 2), sizeof(unsigned char)) ; + if (!ebuf) + return MXT_ERROR_NO_MEM; + + /* Pending - cipher code not yet available */ + + /* Copy full incoming data to tbuf, padding is zero currently */ + memcpy(ebuf, buf, count); + + /* Adjust the padding, add to end of count */ + do { + + /* Determine if last data packet and padding exists */ + if ((tmp_padding > 0) && (bytesToWrite - data_ofs == 16)) { + + /* add random byte */ + ebuf[count] = mxt->mxt_enc.renc_byte; + tmp_padding -= 1; /* reduce by 1 for random data byte */ + padding_ofs = count + 1; /* random data byte */ + + /* add the padding to the last data bytes */ + while (tmp_padding > 0) { + /* Repeat until padding is done*/ + temp = MIN(tmp_padding, count); + + /* i.e. ABCDABCDA */ + memcpy(&ebuf[padding_ofs], &buf[0], temp); + tmp_padding -= temp; + padding_ofs = padding_ofs + temp; + } + } + + data_ofs += 16; + + } while (data_ofs < bytesToWrite); + + /* Pending - Cipher code not yet available */ + + /* Copy encrypted content shifted by datasize */ + memcpy(&tbuf[2], &ebuf[0], msg_length); + + free(ebuf); + } else { + memcpy(&tbuf[2], buf, count); + } + } else if (CHECK_BIT(mxt->mxt_enc.encryption_state, MSG_ENCRYPTED)) { + if (mxt->mxt_enc.enc_cfg_write == true) { + /* buf has data size bytes, that will be] zero'ed later */ + memcpy(&tbuf[0], buf, count); + } else { + /* Internal write from function, count is less datasize */ + memcpy(&tbuf[2], buf, count); + } + } else { /* Normal write, no encryption */ + memcpy(&tbuf[0], buf, count); + } + +if ((CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED)) && + (mxt->mxt_enc.enc_cfg_write == false)) { + /* Write data and adjust the datasize, not for cfg file writes */ + do { + if ((mxt->mxt_enc.encryption_state & CFG_DEV_MASK) == CFG_DEV_MASK) { + if (start_register >= ((mxt->mxt_dev.t38_addr + mxt->mxt_dev.t38_size))) { + if (datasize > mxt->mxt_enc.enc_blocksize) { + msg_count = 48; + tbuf[0] = msg_count & 0xff; + tbuf[1] = (msg_count >> 8) & 0xff; + } else if (datasize < 16) { + msg_count = 16; + tbuf[0] = datasize & 0xff; + tbuf[1] = (datasize >> 8) & 0xff; + } else { + msg_count = msg_length; + tbuf[0] = datasize & 0xff; + tbuf[1] = (datasize >> 8) & 0xff; + } + } else { + tbuf[0] = 0x00; + tbuf[1] = 0x00; + msg_count = msg_length; + } + } else { /* MSG */ + /* Make datasize = 0x0000 for MSG encrypted ?? */ + tbuf[0] = 0x00; + tbuf[1] = 0x00; + msg_count = msg_length; + } + + /* Workaround for legacy driver, otherwise add 2 to msg_count */ + ret = write(fd, tbuf + bytes_written, msg_count + 2); + printf("ret %d\n", ret); + if (ret == 0) { + ret = MXT_ERROR_IO; + goto close; + } else if (ret < 0) { + mxt_err(mxt->ctx, "Error %s (%d) writing to register", strerror(errno), errno); + ret = mxt_errno_to_rc(errno); + goto close; + } + + bytesToWrite -= msg_count; + datasize =- msg_count; + bytes_written += ret; + + } while (bytesToWrite > 0); + +} else { /* for config file writes where data size is embedded */ + bytes_written = 0; + bytesToWrite = count; + while (bytes_written < count) { - ret = write(fd, buf+bytes_written, count - bytes_written); + ret = write(fd, tbuf + bytes_written, bytesToWrite); if (ret == 0) { ret = MXT_ERROR_IO; goto close; @@ -575,7 +716,9 @@ int sysfs_write_register(struct mxt_device *mxt, unsigned char const *buf, } bytes_written += ret; + } +} ret = MXT_SUCCESS; diff --git a/src/libmaxtouch/sysfs/sysfs_device.h b/src/libmaxtouch/sysfs/sysfs_device.h index be536409..acdee3b5 100644 --- a/src/libmaxtouch/sysfs/sysfs_device.h +++ b/src/libmaxtouch/sysfs/sysfs_device.h @@ -79,7 +79,7 @@ int sysfs_new_device(struct libmaxtouch_ctx *ctx, struct mxt_conn_info **conn, c int sysfs_read_register(struct mxt_device *mxt, unsigned char *buf, int start_register, size_t count, size_t *bytes_transferred); int sysfs_bootloader_read(struct mxt_device *mxt, unsigned char *buf, int count); int sysfs_bootloader_write(struct mxt_device *mxt, unsigned const char *buf, int count); -int sysfs_write_register(struct mxt_device *mxt, unsigned char const *buf, int start_register, size_t count); +int sysfs_write_register(struct mxt_device *mxt, unsigned char const *buf, int start_register, size_t count, size_t padding); int sysfs_set_debug(struct mxt_device *mxt, bool debug_state); int sysfs_get_debug(struct mxt_device *mxt, bool *value); int sysfs_set_debug_irq(struct mxt_device *mxt, bool debug_state); diff --git a/src/mxt-app/menu.c b/src/mxt-app/menu.c index 563445af..c0c97cb2 100644 --- a/src/mxt-app/menu.c +++ b/src/mxt-app/menu.c @@ -69,18 +69,26 @@ static void load_config(struct mxt_device *mxt) //****************************************************************************** /// \brief Save config to file -static void save_config(struct mxt_device *mxt) +static int save_config(struct mxt_device *mxt) { char cfg_file[255]; + uint16_t format; /* Save config file */ printf("Give cfg file name: "); if (scanf("%255s", cfg_file) != 1) { printf("Input parse error\n"); - return; + return MXT_ERROR_BAD_INPUT; + } + + printf("Enter config version format 0 or 3, other values are invalid: "); + + if (scanf("%hu", &format) == EOF) { + fprintf(stderr, "Could not handle the input, exiting"); + return MXT_ERROR_BAD_INPUT; } - if (mxt_save_config_file(mxt, cfg_file) == MXT_SUCCESS) { + if (mxt_save_config_file(mxt, cfg_file, format) == MXT_SUCCESS) { printf("Successfully saved configuration to file\n"); } else { printf("Failed to save configuration\n"); diff --git a/src/mxt-app/mxt_app.c b/src/mxt-app/mxt_app.c index 1be74289..dc546a9e 100644 --- a/src/mxt-app/mxt_app.c +++ b/src/mxt-app/mxt_app.c @@ -41,6 +41,8 @@ #include "libmaxtouch/log.h" #include "libmaxtouch/utilfuncs.h" #include "libmaxtouch/info_block.h" +#include "serial_data.h" +#include "libmaxtouch/msg.h" #include "broken_line.h" #include "sensor_variant.h" @@ -108,6 +110,7 @@ static void print_usage(char *prog_name) "Configuration file commands:\n" " --load FILE : upload cfg from FILE in .xcfg or OBP_RAW format\n" " --save FILE : save cfg to FILE in .xcfg or OBP_RAW format\n" + " --format N : save in specific format N - 0 or 3\n" " --backup[=COMMAND] : backup configuration to NVRAM\n" " --checksum FILE : verify .xcfg or OBP_RAW file config checksum\n" "\n" @@ -226,7 +229,7 @@ int main (int argc, char *argv[]) uint8_t t37_file_attr = 0; /* 0 - write, 1 - append */ uint8_t t37_mode = DELTAS_MODE; uint8_t bi2c_addr = 0x4a; - uint8_t format = false; + uint8_t format = 0; uint16_t port = 4000; int i2c_block_size = I2C_DEV_MAX_BLOCK; uint8_t t68_datatype = 1; @@ -945,6 +948,7 @@ int main (int argc, char *argv[]) case CMD_INFO: mxt_verb(ctx, "CMD_INFO"); mxt_print_info_block(mxt); + mxt_print_config_crc(mxt); ret = MXT_SUCCESS; break; @@ -976,7 +980,7 @@ int main (int argc, char *argv[]) break; case CMD_OD_TEST: - mxt_verb(ctx, "CMD_TEST"); + mxt_verb(ctx, "CMD_OD_TEST"); ret = run_self_tests(mxt, ondemand_test_cmd, 1); break; @@ -1079,7 +1083,8 @@ int main (int argc, char *argv[]) case CMD_SAVE_CFG: mxt_verb(ctx, "CMD_SAVE_CFG"); mxt_verb(ctx, "filename:%s", strbuf); - ret = mxt_save_config_file(mxt, strbuf); + mxt_verb(ctx, "format %d", format); + ret = mxt_save_config_file(mxt, strbuf, format); break; case CMD_SELF_CAP_TUNE_CONFIG: @@ -1091,7 +1096,7 @@ int main (int argc, char *argv[]) case CMD_CRC_CHECK: mxt_verb(ctx, "CMD_CRC_CHECK"); mxt_verb(ctx, "filename:%s", strbuf); - ret = mxt_checkcrc(ctx, mxt, strbuf); + ret = mxt_checkcrc(mxt, strbuf); break; case CMD_NONE: diff --git a/src/mxt-app/mxt_app.h b/src/mxt-app/mxt_app.h index 060e0a5c..a5716029 100644 --- a/src/mxt-app/mxt_app.h +++ b/src/mxt-app/mxt_app.h @@ -33,6 +33,11 @@ __typeof__ (b) _b = (b); \ _a < _b ? _a : _b; }) +#define MAX(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) + /* Object offsets */ #define T100_XORIGIN_OFFSET 0x08 #define T100_YORIGIN_OFFSET 0x13 diff --git a/src/mxt-app/self_test.c b/src/mxt-app/self_test.c index 05f8ef4c..96c4980b 100644 --- a/src/mxt-app/self_test.c +++ b/src/mxt-app/self_test.c @@ -378,7 +378,7 @@ int run_self_tests(struct mxt_device *mxt, uint8_t cmd, bool type) uint8_t disable_t10 = 0; int ret; - if (type == 0){ + if (type == 0) { t25_addr = mxt_get_object_address(mxt, SPT_SELFTEST_T25, 0); diff --git a/src/mxt-app/serial_data.c b/src/mxt-app/serial_data.c index 747bd7d9..896090e9 100644 --- a/src/mxt-app/serial_data.c +++ b/src/mxt-app/serial_data.c @@ -27,51 +27,7 @@ // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //------------------------------------------------------------------------------ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmaxtouch/libmaxtouch.h" -#include "libmaxtouch/info_block.h" -#include "libmaxtouch/utilfuncs.h" -#include "libmaxtouch/log.h" - -#include "mxt_app.h" -#include "buffer.h" - -#define T68_CTRL 0 -#define T68_CTRL_ENABLE (1 << 0) -#define T68_CTRL_RPTEN (1 << 1) -#define T68_DATATYPE 3 - -#define T68_CMD_NONE 0 -#define T68_CMD_START 1 -#define T68_CMD_CONTINUE 2 -#define T68_CMD_END 3 - -#define T68_LENGTH 5 -#define T68_DATA 6 - -#define T68_TIMEOUT 30 - -//****************************************************************************** -/// \brief T68 Serial Data Command Context object -struct t68_ctx { - struct mxt_device *mxt; - struct libmaxtouch_ctx *lc; - const char *filename; - struct mxt_buffer buf; - uint16_t t68_addr; - uint8_t t68_size; - uint16_t t68_cmd_addr; - uint16_t t68_data_size; - uint16_t t68_datatype; -}; +#include "serial_data.h" //****************************************************************************** /// \brief Print T68 status messages @@ -118,14 +74,22 @@ static int mxt_t68_get_status(struct mxt_device *mxt, uint8_t *msg, /// \return #mxt_rc static int mxt_t68_command(struct t68_ctx *ctx, uint8_t cmd) { - int ret; + int ret = 0; + + ctx->mxt->mxt_enc.enc_cfg_write = false; mxt_verb(ctx->lc, "Writing %u to CMD register", cmd); ret = mxt_write_register(ctx->mxt, &cmd, ctx->t68_cmd_addr, 1); if (ret) - return ret; + goto t68_command_end; + + ret = mxt_read_messages_sigint(ctx->mxt, T68_TIMEOUT, ctx, mxt_t68_get_status); + if (ret) + goto t68_command_end; - return mxt_read_messages_sigint(ctx->mxt, T68_TIMEOUT, ctx, mxt_t68_get_status); +t68_command_end: + ctx->mxt->mxt_enc.enc_cfg_write = true; + return ret; } //****************************************************************************** @@ -133,17 +97,19 @@ static int mxt_t68_command(struct t68_ctx *ctx, uint8_t cmd) /// \return #mxt_rc static int mxt_t68_enable(struct t68_ctx *ctx) { - int ret; + int ret = 0; uint8_t cmd = T68_CTRL_RPTEN | T68_CTRL_ENABLE; + ctx->mxt->mxt_enc.enc_cfg_write = false; + mxt_dbg(ctx->lc, "Enabling T68 object"); - mxt_verb(ctx->lc, "Writing %u to ctrl register", cmd); + mxt_dbg(ctx->lc, "Writing %u to ctrl register", cmd); ret = mxt_write_register(ctx->mxt, &cmd, ctx->t68_addr + T68_CTRL, 1); - if (ret) - return ret; - return MXT_SUCCESS; + ctx->mxt->mxt_enc.enc_cfg_write = true; + + return ret; } //****************************************************************************** @@ -197,7 +163,7 @@ static int mxt_t68_load_file(struct t68_ctx *ctx) mxt_warn(ctx->lc, "Unable to parse datatype"); } else { ctx->t68_datatype = c; - mxt_info(ctx->lc, "DATATYPE set to %u by file", ctx->t68_datatype); + mxt_dbg(ctx->lc, "DATATYPE set to %u by file", ctx->t68_datatype); } } @@ -245,9 +211,18 @@ static int mxt_t68_load_file(struct t68_ctx *ctx) /// \return #mxt_rc static int mxt_t68_write_length(struct t68_ctx *ctx, uint8_t length) { + int ret; + + + ctx->mxt->mxt_enc.enc_cfg_write = false; + mxt_dbg(ctx->lc, "Writing LENGTH=%u", length); - return mxt_write_register(ctx->mxt, &length, ctx->t68_addr + T68_LENGTH, 1); + ret = mxt_write_register(ctx->mxt, &length, ctx->t68_addr + T68_LENGTH, 1); + + ctx->mxt->mxt_enc.enc_cfg_write = true; + + return ret; } //****************************************************************************** @@ -255,15 +230,22 @@ static int mxt_t68_write_length(struct t68_ctx *ctx, uint8_t length) /// \return #mxt_rc static int mxt_t68_zero_data(struct t68_ctx *ctx) { + int ret; + + ctx->mxt->mxt_enc.enc_cfg_write = false; + uint8_t zeros[ctx->t68_data_size]; mxt_dbg(ctx->lc, "Zeroing DATA"); memset(&zeros, 0, sizeof(zeros)); - return mxt_write_register(ctx->mxt, zeros, + ret = mxt_write_register(ctx->mxt, zeros, ctx->t68_addr + T68_DATA, sizeof(zeros)); + ctx->mxt->mxt_enc.enc_cfg_write = true; + + return ret; } //****************************************************************************** @@ -271,49 +253,55 @@ static int mxt_t68_zero_data(struct t68_ctx *ctx) /// \return #mxt_rc static int mxt_t68_send_frames(struct t68_ctx *ctx) { - int ret; + int ret = 0; size_t offset = 0; - uint16_t frame_size; + uint8_t frame_size = 0; int frame = 1; uint8_t cmd; - while (offset < ctx->buf.size) { - frame_size = MIN(ctx->buf.size - offset, ctx->t68_data_size); + ctx->mxt->mxt_enc.enc_cfg_write = false; + + while (cmd != T68_CMD_END) { + frame_size = MIN(ctx->t68_length - offset, ctx->t68_data_size); - mxt_info(ctx->lc, "Writing frame %u, %u bytes", frame, frame_size); + mxt_dbg(ctx->lc, "Writing frame %u, %u bytes", frame, frame_size); if (frame_size > UCHAR_MAX) { mxt_err(ctx->lc, "Serial data frame size miscalculation"); + ctx->mxt->mxt_enc.enc_cfg_write = true; return MXT_INTERNAL_ERROR; } - ret = mxt_write_register(ctx->mxt, ctx->buf.data + offset, - ctx->t68_addr + T68_DATA, - frame_size); + ret = mxt_write_register(ctx->mxt, ctx->buf.data + offset, + ctx->t68_addr + T68_DATA, + ctx->t68_data_size); + if (ret) - return ret; + goto t68_send_frames_end; ret = mxt_t68_write_length(ctx, frame_size); if (ret) - return ret; - - offset += frame_size; + goto t68_send_frames_end; if (frame == 1) cmd = T68_CMD_START; - else if (offset >= ctx->buf.size) + else if (offset >= ctx->t68_length) { cmd = T68_CMD_END; - else + } else cmd = T68_CMD_CONTINUE; + offset += frame_size; + ret = mxt_t68_command(ctx, cmd); if (ret) - return ret; + goto t68_send_frames_end; frame++; } - return MXT_SUCCESS; +t68_send_frames_end: + ctx->mxt->mxt_enc.enc_cfg_write = true; + return ret; } //****************************************************************************** @@ -322,12 +310,19 @@ static int mxt_t68_send_frames(struct t68_ctx *ctx) static int mxt_t68_write_datatype(struct t68_ctx *ctx) { uint8_t buf[2]; + int ret = 0; + + ctx->mxt->mxt_enc.enc_cfg_write = false; buf[0] = (ctx->t68_datatype & 0xFF); buf[1] = (ctx->t68_datatype & 0xFF00) >> 8; - mxt_info(ctx->lc, "Writing %u to DATATYPE register", ctx->t68_datatype); - return mxt_write_register(ctx->mxt, &buf[0], ctx->t68_addr + T68_DATATYPE, sizeof(buf)); + mxt_dbg(ctx->lc, "Writing %u to DATATYPE register", ctx->t68_datatype); + ret = mxt_write_register(ctx->mxt, &buf[0], ctx->t68_addr + T68_DATATYPE, sizeof(buf)); + + ctx->mxt->mxt_enc.enc_cfg_write = true; + + return ret; } //****************************************************************************** @@ -351,10 +346,10 @@ static int mxt_t68_check_power_cfg(struct t68_ctx *ctx) mxt_verb(ctx->lc, "T7 IDLEACQINT=%u ACTVACQINT=%u", buf[0], buf[1]); if ((buf[0] == 0) || (buf[1] == 0)) { - mxt_err(ctx->lc, "Warning: The T7 power configuration object shows that the chip " - "is in deep sleep, and so will not process T68 serial data " - "commands. Please set the T7 power configuration idle acquisition " - "interval to a non-zero value and try again."); + mxt_err(ctx->lc, "\nWarning: The T7 power object is in deep sleep,\n" + "and will not process T68 serial data commands.\n" + "Please set the T7 power configuration idle acquisition \n" + "interval to a non-zero value and try again.\n"); return MXT_ERROR_UNEXPECTED_DEVICE_STATE; } else { @@ -396,12 +391,18 @@ int mxt_serial_data_upload(struct mxt_device *mxt, const char *filename, uint16_ /* Set datatype from command line */ ctx.t68_datatype = datatype; + mxt_dbg (ctx.lc, "Loading T68 file"); /* Read input file */ ctx.filename = filename; - ret = mxt_t68_load_file(&ctx); - if (ret) - return ret; + + if (ctx.filename != NULL) { + ret = mxt_t68_load_file(&ctx); + if (ret) + return ret; + } else { + mxt_info (ctx.lc, "File was null"); + } ret = mxt_t68_enable(&ctx); if (ret) @@ -415,22 +416,94 @@ int mxt_serial_data_upload(struct mxt_device *mxt, const char *filename, uint16_ if (ret) goto release; - mxt_info(ctx.lc, "Configuring T68"); + mxt_dbg(ctx.lc, "Configuring T68"); ret = mxt_t68_write_datatype(&ctx); if (ret) goto release; - mxt_info(ctx.lc, "Sending data"); + mxt_dbg(ctx.lc, "Sending data"); ret = mxt_t68_send_frames(&ctx); if (ret) { mxt_err(ctx.lc, "Error sending data"); goto release; } - mxt_info(ctx.lc, "Done"); + mxt_info(ctx.lc, "Load T68 Done"); ret = MXT_SUCCESS; release: mxt_buf_free(&ctx.buf); return ret; } + +//****************************************************************************** +/// \brief Upload file to T68 Serial Data Object +/// \return #mxt_rc +int mxt_load_t68_payload(struct mxt_device *mxt, struct t68_ctx *ctx) +{ + int ret; + + ctx->mxt = mxt; + ctx->lc = mxt->ctx; + + mxt_info(ctx->lc, "Uploading T68 payload"); + + ret = mxt_msg_reset(ctx->mxt); + if (ret) + return ret; + + if (!(CHECK_BIT(mxt->mxt_enc.encryption_state, DEV_ENCRYPTED))) { + mxt_info(ctx->lc, "Checking T7 Power Config"); + ret = mxt_t68_check_power_cfg(ctx); + if (ret) + return ret; + } + + /* Check for existence of T68 object */ + ctx->t68_addr = mxt_get_object_address(ctx->mxt, SERIAL_DATA_COMMAND_T68, 0); + if (ctx->t68_addr == OBJECT_NOT_FOUND) + return MXT_ERROR_OBJECT_NOT_FOUND; + + + /* Calculate position of CMD register */ + ctx->t68_size = mxt_get_object_size(ctx->mxt, SERIAL_DATA_COMMAND_T68); + ctx->t68_cmd_addr = ctx->t68_addr + ctx->t68_size - 3; + + /* Calculate frame size */ + ctx->t68_data_size = ctx->t68_size - 9; + + /* Set datatype from command line */ + //ctx->t68_datatype = datatype; + + ret = mxt_t68_enable(ctx); + if (ret) + return ret; + + ret = mxt_t68_zero_data(ctx); + if (ret) + return ret; + + ret = mxt_t68_write_length(ctx, 0); + if (ret) + return ret; + + mxt_dbg(ctx->lc, "Configuring T68"); + ret = mxt_t68_write_datatype(ctx); + if (ret) + return ret; + + mxt_dbg(ctx->lc, "Sending data"); + ret = mxt_t68_send_frames(ctx); + if (ret) { + mxt_err(ctx->lc, "Error sending data"); + return ret; + } + + mxt_info(ctx->lc, "T68 Done"); + ret = MXT_SUCCESS; + +release_buf: + mxt_buf_free(&ctx->buf); + + return ret; +} \ No newline at end of file diff --git a/src/mxt-app/serial_data.h b/src/mxt-app/serial_data.h new file mode 100644 index 00000000..cb02b40a --- /dev/null +++ b/src/mxt-app/serial_data.h @@ -0,0 +1,84 @@ +#pragma once +//------------------------------------------------------------------------------ +/// \file serial_data.h +/// \brief T68 Serial Data Header +/// \author Michael Gong +//------------------------------------------------------------------------------ +// Copyright 2016 Atmel Corporation. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY ATMEL ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL ATMEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +//------------------------------------------------------------------------------ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libmaxtouch/libmaxtouch.h" +#include "libmaxtouch/info_block.h" +#include "libmaxtouch/utilfuncs.h" +#include "libmaxtouch/log.h" + +#include "mxt_app.h" +#include "buffer.h" + +#define T68_CTRL 0 +#define T68_CTRL_ENABLE (1 << 0) +#define T68_CTRL_RPTEN (1 << 1) +#define T68_DATATYPE 3 + +#define T68_CMD_NONE 0 +#define T68_CMD_START 1 +#define T68_CMD_CONTINUE 2 +#define T68_CMD_END 3 + +#define T68_LENGTH 5 +#define T68_DATA 6 + +#define T68_TIMEOUT 30 + +//****************************************************************************** +/// \brief T68 Serial Data Command Context object +struct t68_ctx { + struct mxt_device *mxt; + struct libmaxtouch_ctx *lc; + const char *filename; + struct mxt_buffer buf; + uint32_t t68_object_id; + uint16_t t68_instance; + uint16_t t68_addr; + uint8_t t68_size; + uint16_t t68_cmd_addr; + uint16_t t68_data_size; + uint16_t t68_datatype; + uint16_t t68_length; + bool t68_last_frame; + uint32_t t68_checksum; +}; + +int mxt_load_t68_payload(struct mxt_device *mxt, struct t68_ctx *ctx); +int mxt_serial_data_upload(struct mxt_device *mxt, const char *filename, uint16_t datatype); \ No newline at end of file