예제 #1
0
//******************************************************************************
/// \brief Disable noise suppression objects
static void disable_noise_suppression(struct mxt_device *mxt)
{
   uint16_t addr;
   uint8_t disable = 0;

   addr = mxt_get_object_address(mxt, PROCG_NOISESUPPRESSION_T22, 0);
   if (addr != OBJECT_NOT_FOUND)
   {
      mxt_write_register(mxt, &disable, addr, 1);
   }

   addr = mxt_get_object_address(mxt, PROCG_NOISESUPPRESSION_T48, 0);
   if (addr != OBJECT_NOT_FOUND)
   {
      mxt_write_register(mxt, &disable, addr, 1);
   }

   addr = mxt_get_object_address(mxt, PROCG_NOISESUPPRESSION_T54, 0);
   if (addr != OBJECT_NOT_FOUND)
   {
      mxt_write_register(mxt, &disable, addr, 1);
   }

   addr = mxt_get_object_address(mxt, PROCG_NOISESUPPRESSION_T62, 0);
   if (addr != OBJECT_NOT_FOUND)
   {
      mxt_write_register(mxt, &disable, addr, 1);
   }
}
예제 #2
0
//******************************************************************************
/// \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;
}
예제 #3
0
//******************************************************************************
/// \brief  Perform fallback reset
/// \return #mxt_rc
static int mxt_send_reset_command(struct mxt_device *mxt, bool bootloader_mode)
{
  int ret;
  uint16_t t6_addr;
  unsigned char write_value = RESET_COMMAND;

  /* Obtain command processor's address */
  t6_addr = mxt_get_object_address(mxt, GEN_COMMANDPROCESSOR_T6, 0);
  if (t6_addr == OBJECT_NOT_FOUND)
    return MXT_ERROR_OBJECT_NOT_FOUND;

  /* The value written determines which mode the chip will boot into */
  if (bootloader_mode) {
    mxt_info(mxt->ctx, "Resetting in bootloader mode");
    write_value = BOOTLOADER_COMMAND;
  } else {
    mxt_info(mxt->ctx, "Sending reset command");
  }

  /* Write to command processor register to perform command */
  ret = mxt_write_register
        (
          mxt, &write_value, t6_addr + MXT_T6_RESET_OFFSET, 1
        );

  return ret;
}
예제 #4
0
//******************************************************************************
/// \brief Write DATATYPE
/// \return #mxt_rc
static int mxt_t68_write_datatype(struct t68_ctx *ctx)
{
  uint8_t buf[2];

  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));
}
예제 #5
0
//******************************************************************************
/// \brief  Send command then check status
/// \return #mxt_rc
static int mxt_t68_command(struct t68_ctx *ctx, uint8_t cmd)
{
  int ret;

  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;

  return mxt_read_messages_sigint(ctx->mxt, T68_TIMEOUT, ctx, mxt_t68_get_status);
}
예제 #6
0
//******************************************************************************
/// \brief Zero entire T68 object
/// \return #mxt_rc
static int mxt_t68_zero_data(struct t68_ctx *ctx)
{
  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,
                            ctx->t68_addr + T68_DATA,
                            sizeof(zeros));
}
예제 #7
0
//******************************************************************************
/// \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);
}
예제 #8
0
//******************************************************************************
/// \brief  Enable T68
/// \return #mxt_rc
static int mxt_t68_enable(struct t68_ctx *ctx)
{
  int ret;
  uint8_t cmd = T68_CTRL_RPTEN | T68_CTRL_ENABLE;

  mxt_dbg(ctx->lc, "Enabling T68 object");
  mxt_verb(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;
}
예제 #9
0
//******************************************************************************
/// \brief Send frames of T68 data to chip
/// \return #mxt_rc
static int mxt_t68_send_frames(struct t68_ctx *ctx)
{
  int ret;
  size_t offset = 0;
  uint16_t frame_size;
  int frame = 1;
  uint8_t cmd;

  while (offset < ctx->buf.size) {
    frame_size = MIN(ctx->buf.size - offset, ctx->t68_data_size);

    mxt_info(ctx->lc, "Writing frame %u, %u bytes", frame, frame_size);

    if (frame_size > UCHAR_MAX) {
      mxt_err(ctx->lc, "Serial data frame size miscalculation");
      return MXT_INTERNAL_ERROR;
    }

    ret = mxt_write_register(ctx->mxt, ctx->buf.data + offset,
                             ctx->t68_addr + T68_DATA,
                             frame_size);
    if (ret)
      return ret;

    ret = mxt_t68_write_length(ctx, frame_size);
    if (ret)
      return ret;

    offset += frame_size;

    if (frame == 1)
      cmd = T68_CMD_START;
    else if (offset >= ctx->buf.size)
      cmd = T68_CMD_END;
    else
      cmd = T68_CMD_CONTINUE;

    ret = mxt_t68_command(ctx, cmd);
    if (ret)
      return ret;

    frame++;
  }

  return MXT_SUCCESS;
}
예제 #10
0
파일: bridge.c 프로젝트: sonntam/obp-utils
//******************************************************************************
/// \brief Handle bridge write
/// \return #mxt_rc
static int bridge_wri_cmd(struct mxt_device *mxt, int sockfd, uint16_t address,
                          char *hex, uint16_t bytes)
{
  int ret;
  uint16_t count;
  const char * const FAIL = "WRP ERR\n";
  const char * const PASS = "******";
  const char *response;
  uint8_t *databuf;

  databuf = calloc(bytes, sizeof(uint8_t));
  if (!databuf) {
    mxt_err(mxt->ctx, "Failed to allocate memory");
    return MXT_ERROR_NO_MEM;
  }

  ret = mxt_convert_hex(hex, databuf, &count, bytes);
  if (ret) {
    response = FAIL;
  } else {
    ret = mxt_write_register(mxt, databuf, address, count);
    if (ret) {
      mxt_verb(mxt->ctx, "WRI OK");
      response = FAIL;
    } else {
      response = PASS;
    }
  }

  ret = write(sockfd, response, strlen(response));
  if (ret < 0) {
    mxt_err(mxt->ctx, "Socket write error: %s (%d)", strerror(errno), errno);
    ret = mxt_errno_to_rc(errno);
  }

  ret = MXT_SUCCESS;
  free(databuf);
  return ret;
}
예제 #11
0
//******************************************************************************
/// \brief  Backup configuration settings to non-volatile memory
/// \return #mxt_rc
int mxt_backup_config(struct mxt_device *mxt, uint8_t backup_command)
{
  int ret;
  uint16_t t6_addr;

  /* Obtain command processor's address */
  t6_addr = mxt_get_object_address(mxt, GEN_COMMANDPROCESSOR_T6, 0);
  if (t6_addr == OBJECT_NOT_FOUND)
    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
        );

  if (ret == MXT_SUCCESS)
    mxt_info(mxt->ctx, "Backed up settings to the non-volatile memory");
  else
    mxt_err(mxt->ctx, "Failed to back up settings");

  return ret;
}
예제 #12
0
//******************************************************************************
/// \brief  Issue REPORTALL command to device
/// \return #mxt_rc
int mxt_report_all(struct mxt_device *mxt)
{
  int ret;
  uint16_t t6_addr;
  const uint8_t report_all_cmd = 0xff;

  /* Obtain command processor's address */
  t6_addr = mxt_get_object_address(mxt, GEN_COMMANDPROCESSOR_T6, 0);
  if (t6_addr == OBJECT_NOT_FOUND)
    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
        );

  if (ret == MXT_SUCCESS)
    mxt_info(mxt->ctx, "REPORTALL command issued");
  else
    mxt_err(mxt->ctx, "Failed to issue REPORTALL command");

  return ret;
}
예제 #13
0
//******************************************************************************
/// \brief  Calibrate maxtouch chip
/// \return 0 = success, negative = fail
int mxt_calibrate_chip(struct mxt_device *mxt)
{
  int ret;
  uint16_t t6_addr;
  unsigned char write_value = CALIBRATE_COMMAND;

  /* Obtain command processor's address */
  t6_addr = mxt_get_object_address(mxt, GEN_COMMANDPROCESSOR_T6, 0);
  if (t6_addr == OBJECT_NOT_FOUND)
    return MXT_ERROR_OBJECT_NOT_FOUND;

  mxt_flush_msgs(mxt);

  /* Write to command processor register to perform command */
  ret = mxt_write_register(mxt, &write_value, t6_addr + MXT_T6_CALIBRATE_OFFSET, 1);
  if (ret == 0) {
    mxt_info(mxt->ctx, "Sent calibration command");
  } else {
    mxt_err(mxt->ctx, "Failed to send calibration command");
  }

  int state = 0;
  int flag = false;

  ret = mxt_read_messages(mxt, MXT_CALIBRATE_TIMEOUT, &state,
                          handle_calibrate_msg, &flag);
  if (ret == MXT_ERROR_TIMEOUT) {
    mxt_warn(mxt->ctx, "WARN: timed out waiting for calibrate status");
    return MXT_SUCCESS;
  } else if (ret) {
    mxt_err(mxt->ctx, "FAIL: device calibration failed");
    return ret;
  }

  return MXT_SUCCESS;
}
예제 #14
0
//******************************************************************************
/// \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;
}
예제 #15
0
//******************************************************************************
/// \brief Write LENGTH
/// \return #mxt_rc
static int mxt_t68_write_length(struct t68_ctx *ctx, uint8_t length)
{
  mxt_dbg(ctx->lc, "Writing LENGTH=%u", length);

  return mxt_write_register(ctx->mxt, &length, ctx->t68_addr + T68_LENGTH, 1);
}