//****************************************************************************** /// \brief Retrieve a single page of diagnostic data /// \return #mxt_rc static int mxt_get_t37_page(struct t37_ctx *ctx) { int failures; int ret; uint8_t read_command = 1; uint8_t page_up_cmd = PAGE_UP; if (ctx->pass == 0 && ctx->page == 0) { mxt_dbg(ctx->lc, "Writing mode command %02X", ctx->mode); ret = mxt_write_register(ctx->mxt, &ctx->mode, ctx->diag_cmd_addr, 1); if (ret) return ret; } else { ret = mxt_write_register(ctx->mxt, &page_up_cmd, ctx->diag_cmd_addr, 1); if (ret) return ret; } /* Read back diagnostic register in T6 command processor until it has been * cleared. This means that the chip has actioned the command */ failures = 0; while (read_command) { usleep(500); ret = mxt_read_register(ctx->mxt, &read_command, ctx->diag_cmd_addr, 1); if (ret) { mxt_err(ctx->lc, "Failed to read the status of diagnostic mode command"); return ret; } if (read_command) { failures++; if (failures > 500) { mxt_err(ctx->lc, "Timeout waiting for command to be actioned"); return MXT_ERROR_TIMEOUT; } } } ret = mxt_read_register(ctx->mxt, (uint8_t *)ctx->t37_buf, ctx->t37_addr, ctx->t37_size); if (ret) { mxt_err(ctx->lc, "Failed to read page"); return ret; } if (ctx->t37_buf->mode != ctx->mode) { mxt_err(ctx->lc, "Bad mode in diagnostic data read"); return MXT_ERROR_UNEXPECTED_DEVICE_STATE; } if (ctx->t37_buf->page != (ctx->pages_per_pass * ctx->pass + ctx->page)) { mxt_err(ctx->lc, "Bad page in diagnostic data read"); return MXT_ERROR_UNEXPECTED_DEVICE_STATE; } return MXT_SUCCESS; }
/*! * @brief Reads the information block from the chip. * @return #mxt_rc */ int mxt_read_info_block(struct mxt_device *mxt) { int ret; /* Read the ID Information from the chip */ uint8_t *info_blk = (uint8_t *)calloc(1, sizeof(struct mxt_id_info)); if (info_blk == NULL) { mxt_err(mxt->ctx, "Memory allocation failure"); return MXT_ERROR_NO_MEM; } ret = mxt_read_register(mxt, info_blk, 0, sizeof(struct mxt_id_info)); if (ret) { mxt_err(mxt->ctx, "Failed to read ID information"); return ret; } /* Determine the number of bytes for checksum calculation */ int num_objects = ((struct mxt_id_info*) info_blk)->num_objects; size_t crc_area_size = sizeof(struct mxt_id_info) + num_objects * sizeof(struct mxt_object); /* Allocate space to read Information Block AND Checksum from the chip */ size_t info_block_size = crc_area_size + sizeof(struct mxt_raw_crc); info_blk = (uint8_t *)realloc(info_blk, info_block_size); if (info_blk == NULL) { mxt_err(mxt->ctx, "Memory allocation failure"); return MXT_ERROR_NO_MEM; } /* Read the entire Information Block from the chip */ ret = mxt_read_register(mxt, info_blk, 0, info_block_size); if (ret) { mxt_err(mxt->ctx, "Failed to read Information Block"); return ret; } /* Update pointers in device structure */ mxt->info.raw_info = info_blk; mxt->info.id = (struct mxt_id_info*) info_blk; mxt->info.objects = (struct mxt_object*)(info_blk + sizeof(struct mxt_id_info)); mxt->info.crc = convert_crc((struct mxt_raw_crc*) (info_blk + crc_area_size)); /* Calculate and compare Information Block Checksum */ ret = calculate_crc(mxt, mxt->info.crc, info_blk, crc_area_size); if (ret) return ret; return MXT_SUCCESS; }
//****************************************************************************** /// \brief Print T25 limits for each enabled touch object static void print_t25_limits(struct mxt_device *mxt, uint16_t t25_addr) { int i; struct mxt_object obj; int touch_object = 0; uint8_t buf[4]; uint16_t upsiglim; uint16_t losiglim; int instance; for (i = 0; i < mxt->info.id->num_objects; i++) { obj = mxt->info.objects[i]; switch (obj.type) { case TOUCH_MULTITOUCHSCREEN_T9: case TOUCH_SINGLETOUCHSCREEN_T10: case TOUCH_XSLIDER_T11: case TOUCH_YSLIDER_T12: case TOUCH_XWHEEL_T13: case TOUCH_YWHEEL_T14: case TOUCH_KEYARRAY_T15: case TOUCH_PROXIMITY_T23: case TOUCH_KEYSET_T31: case TOUCH_XSLIDERSET_T32: for (instance = 0; (instance < MXT_INSTANCES(obj)); instance++) { mxt_read_register(mxt, (uint8_t *)&buf, mxt_get_start_position(obj, instance), 1); mxt_info(mxt->ctx, "%s[%d] %s", mxt_get_object_name(obj.type), instance, buf[0] & 0x01 ? "enabled":"disabled"); mxt_read_register(mxt, (uint8_t *)&buf, t25_addr + 2 + touch_object * 4, 4); upsiglim = (uint16_t)((buf[1] << 8u) | buf[0]); losiglim = (uint16_t)((buf[3] << 8u) | buf[2]); mxt_info(mxt->ctx, " UPSIGLIM:%d", upsiglim); mxt_info(mxt->ctx, " LOSIGLIM:%d", losiglim); touch_object++; } break; default: break; } } }
//****************************************************************************** /// \brief Check chip is not in deep sleep /// \return #mxt_rc static int mxt_t68_check_power_cfg(struct t68_ctx *ctx) { uint16_t t7_addr; uint8_t buf[2]; int ret; /* Skip if object not present */ t7_addr = mxt_get_object_address(ctx->mxt, GEN_POWERCONFIG_T7, 0); if (t7_addr == OBJECT_NOT_FOUND) return MXT_SUCCESS; ret = mxt_read_register(ctx->mxt, &buf[0], t7_addr, sizeof(buf)); if (ret) return ret; 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."); return MXT_ERROR_UNEXPECTED_DEVICE_STATE; } else { return MXT_SUCCESS; } }
//****************************************************************************** /// \brief Get next MSG into byte buffer /// \return #mxt_rc int t44_get_msg_bytes(struct mxt_device *mxt, unsigned char *buf, size_t buflen, int *count) { int ret; uint16_t addr; uint16_t size; addr = mxt_get_object_address(mxt, GEN_MESSAGEPROCESSOR_T5, 0); if (addr == OBJECT_NOT_FOUND) return MXT_ERROR_OBJECT_NOT_FOUND; /* Do not read CRC byte */ size = mxt_get_object_size(mxt, GEN_MESSAGEPROCESSOR_T5) - 1; if (size > buflen) { mxt_err(mxt->ctx, "Buffer too small!"); return MXT_ERROR_NO_MEM; } ret = mxt_read_register(mxt, buf, addr, size); if (ret) return ret; /* Check for invalid message */ if (buf[0] == 255u) { mxt_verb(mxt->ctx, "Invalid message"); return MXT_ERROR_NO_MESSAGE; } *count = size; return MXT_SUCCESS; }
//****************************************************************************** /// \brief Handle bridge read /// \return #mxt_rc static int bridge_rea_cmd(struct mxt_device *mxt, int sockfd, uint16_t address, uint16_t count) { int ret; uint8_t *databuf; char *response; const char * const PREFIX = "RRP "; size_t response_len; int i; databuf = calloc(count, sizeof(uint8_t)); if (!databuf) { mxt_err(mxt->ctx, "Failed to allocate memory"); return MXT_ERROR_NO_MEM; } /* Allow for newline/null byte */ response_len = strlen(PREFIX) + count*2 + 1; response = calloc(response_len, sizeof(uint8_t)); if (!response) { mxt_err(mxt->ctx, "Failed to allocate memory"); ret = MXT_ERROR_NO_MEM; goto free_databuf; } strcpy(response, PREFIX); ret = mxt_read_register(mxt, databuf, address, count); if (ret) { mxt_warn(mxt->ctx, "RRP ERR"); strcpy(response + strlen(PREFIX), "ERR\n"); response_len = strlen(response); } else { for (i = 0; i < count; i++) { sprintf(response + strlen(PREFIX) + i*2, "%02X", databuf[i]); } mxt_info(mxt->ctx, "%s", response); response[response_len - 1] = '\n'; } ret = write(sockfd, response, response_len); if (ret < 0) { mxt_err(mxt->ctx, "Socket write error: %s (%d)", strerror(errno), errno); ret = mxt_errno_to_rc(errno); goto free; } ret = MXT_SUCCESS; free: free(response); free_databuf: free(databuf); return ret; }
//****************************************************************************** /// \brief Get number of messages /// \return #mxt_rc int t44_get_msg_count(struct mxt_device *mxt, int *count_out) { uint16_t addr; int ret; uint8_t count; addr = mxt_get_object_address(mxt, SPT_MESSAGECOUNT_T44, 0); if (addr == OBJECT_NOT_FOUND) return MXT_ERROR_OBJECT_NOT_FOUND; /* Get T44 count */ ret = mxt_read_register(mxt, &count, addr, 1); if (ret) return ret; *count_out = count; return MXT_SUCCESS; }