//****************************************************************************** /// \brief Run self test int run_self_tests(struct mxt_device *mxt, uint8_t cmd) { uint16_t t25_addr; uint8_t enable = 3; mxt_msg_reset(mxt); // Enable self test object & reporting t25_addr = mxt_get_object_address(mxt, SPT_SELFTEST_T25, 0); mxt_info(mxt->ctx, "Enabling self test object"); mxt_write_register(mxt, &enable, t25_addr, 1); mxt_info(mxt->ctx, "Disabling noise suppression"); disable_noise_suppression(mxt); print_t25_limits(mxt, t25_addr); mxt_info(mxt->ctx, "Running tests"); mxt_write_register(mxt, &cmd, t25_addr + 1, 1); return self_test_handle_messages(mxt); }
//****************************************************************************** /// \brief Main bridge function to handle a single connection /// \return #mxt_rc static int bridge(struct mxt_device *mxt, int sockfd) { int ret, pollret; struct pollfd fds[2]; int fopts = 0; int debug_ng_fd = 0; int numfds = 1; int timeout; mxt_info(mxt->ctx, "Connected"); ret = mxt_msg_reset(mxt); if (ret) mxt_err(mxt->ctx, "Failure to reset msgs"); fds[0].fd = sockfd; fds[0].events = POLLIN | POLLERR; ret = send_chip_attach(mxt, sockfd); if (ret) return ret; while (1) { debug_ng_fd = mxt_get_msg_poll_fd(mxt); if (debug_ng_fd) { fds[1].fd = debug_ng_fd; fds[1].events = POLLPRI; numfds = 2; timeout = -1; } else { timeout = 100; // milliseconds } pollret = poll(fds, numfds, timeout); if (pollret == -1 && errno == EINTR) { mxt_dbg(mxt->ctx, "Interrupted"); continue; } else if (pollret == -1) { mxt_err(mxt->ctx, "Poll returned %d (%s)", errno, strerror(errno)); ret = mxt_errno_to_rc(errno); goto disconnect; } /* Detect socket disconnect */ if (fcntl(sockfd, F_GETFL, &fopts) < 0) { ret = MXT_SUCCESS; mxt_dbg(mxt->ctx, "Socket disconnected"); goto disconnect; } if (fds[0].revents) { ret = handle_cmd(mxt, sockfd); if (ret) { mxt_dbg(mxt->ctx, "handle_cmd returned %d", ret); goto disconnect; } } /* If timeout or msg poll fd event */ if (pollret == 0 || fds[1].revents) { ret = handle_messages(mxt, sockfd); if (ret) goto disconnect; } } disconnect: mxt_info(mxt->ctx, "Disconnected"); return ret; }
//****************************************************************************** /// \brief Run self cap tuning procedure without updating the config /// checksum /// \return #mxt_rc int mxt_self_cap_tune(struct mxt_device *mxt, mxt_app_cmd cmd) { int ret; uint16_t t6_addr; uint16_t t109_addr; uint8_t backupnv_value; uint8_t t109_command; mxt_msg_reset(mxt); // Enable self test object & reporting t6_addr = mxt_get_object_address(mxt, GEN_COMMANDPROCESSOR_T6, 0); if (t6_addr == OBJECT_NOT_FOUND) return MXT_ERROR_OBJECT_NOT_FOUND; t109_addr = mxt_get_object_address(mxt, SPT_SELFCAPGLOBALCONFIG_T109, 0); if (t109_addr == OBJECT_NOT_FOUND) return MXT_ERROR_OBJECT_NOT_FOUND; mxt_info(mxt->ctx, "Stopping T70"); backupnv_value = 0x33; ret = mxt_write_register(mxt, &backupnv_value, t6_addr + MXT_T6_BACKUPNV_OFFSET, 1); if (ret) return ret; // Wait for backup operation to complete (otherwise T109 report may be missed) mxt_msg_wait(mxt, 100); mxt_info(mxt->ctx, "Tuning"); t109_command = T109_CMD_TUNE; mxt_info(mxt->ctx, "Writing %u to T109 CMD register", cmd); ret = mxt_write_register(mxt, &t109_command, t109_addr + T109_CMD_OFFSET, 1); if (ret) return ret; ret = mxt_read_messages(mxt, T109_TIMEOUT, &t109_command, mxt_self_cap_command, (int *)&mxt_sigint_rx); if (ret) return ret; switch (cmd) { case CMD_SELF_CAP_TUNE_CONFIG: mxt_info(mxt->ctx, "Store to Config"); t109_command = T109_CMD_STORE_TO_CONFIG_RAM; break; default: case CMD_SELF_CAP_TUNE_NVRAM: mxt_info(mxt->ctx, "Store to NVRAM"); t109_command = T109_CMD_STORE_TO_NVM; break; } mxt_info(mxt->ctx, "Writing %u to T109 CMD register", cmd); ret = mxt_write_register(mxt, &t109_command, t109_addr + T109_CMD_OFFSET, 1); if (ret) return ret; ret = mxt_read_messages(mxt, 100, (void *) &t109_command, mxt_self_cap_command, (int *)&mxt_sigint_rx); if (ret) return ret; mxt_info(mxt->ctx, "Saving configuration"); ret = mxt_backup_config(mxt, BACKUPNV_COMMAND); if (ret) return ret; ret = mxt_reset_chip(mxt, false); if (ret) return ret; return MXT_SUCCESS; }
//****************************************************************************** /// \brief Upload file to T68 Serial Data Object /// \return #mxt_rc int mxt_serial_data_upload(struct mxt_device *mxt, const char *filename, uint16_t datatype) { int ret; struct t68_ctx ctx; ctx.mxt = mxt; ctx.lc = mxt->ctx; ret = mxt_msg_reset(mxt); if (ret) return ret; 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(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(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; /* Read input file */ ctx.filename = filename; ret = mxt_t68_load_file(&ctx); if (ret) return ret; ret = mxt_t68_enable(&ctx); if (ret) goto release; ret = mxt_t68_zero_data(&ctx); if (ret) goto release; ret = mxt_t68_write_length(&ctx, 0); if (ret) goto release; mxt_info(ctx.lc, "Configuring T68"); ret = mxt_t68_write_datatype(&ctx); if (ret) goto release; mxt_info(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"); ret = MXT_SUCCESS; release: mxt_buf_free(&ctx.buf); return ret; }