Example #1
0
static void print_matrix(struct libmaxtouch_ctx *ctx, double *mat, int n) {
  int i, j;

  mxt_verb(ctx, "\nMatrix:");
  for (i = 0; i < n; i++) {
    /* each row */
    for (j = 0; j < n; j++) {
      /* each column */
      mxt_verb(ctx, "%0.2f\t\t", mat[i * n + j]);
    }
    mxt_verb(ctx, "\n");
  }
  return;
}
Example #2
0
//******************************************************************************
/// \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;
  }
}
Example #3
0
//******************************************************************************
/// \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;
}
Example #4
0
//******************************************************************************
/// \brief  Write packet to MXT chip
/// \return Number of databytes sent
static int hidraw_write_packet(struct mxt_device *mxt, struct hid_packet *write_pkt, uint8_t *byte_count)
{
  int ret;
  uint8_t pkt_size = write_pkt->rx_bytes + 4; /* allowing for header */

  if ((ret = write(mxt->conn->hidraw.fd, write_pkt, pkt_size)) != pkt_size) {
    mxt_verb(mxt->ctx, "HIDRAW retry");
    usleep(HIDRAW_WRITE_RETRY_DELAY_US);
    if ((ret = write(mxt->conn->hidraw.fd, &write_pkt, pkt_size)) != pkt_size) {
      mxt_err(mxt->ctx, "Error %s (%d) writing to hidraw",
              strerror(errno), errno);
      ret = mxt_errno_to_rc(errno);
    }
  }

  mxt_log_buffer(mxt->ctx, LOG_VERBOSE, "PKT TX:",
                 (const unsigned char *) write_pkt, pkt_size);

  *byte_count = ret - 6;

  mxt_dbg(mxt->ctx, "Sending packet: size: %d No. data bytes TX: %d",
          pkt_size, *byte_count);

  return MXT_SUCCESS;
}
Example #5
0
/*!
 * @param  mxt Maxtouch Device
 * @param  object_type Object ID number.
 * @param  instance Instance number of the object.
 *
 * @brief  Returns the start address of the selected object and instance number
 *         in the chip's memory map.
 * @return Object address, or OBJECT_NOT_FOUND if object/instance not found.
 */
uint16_t mxt_get_object_address(struct mxt_device *mxt, uint16_t object_type, uint8_t instance)
{
  struct mxt_id_info *id = mxt->info.id;
  int i = 0;
  struct mxt_object obj;

  for (i = 0; i < id->num_objects; i++) {
    obj = mxt->info.objects[i];

    /* Does object type match? */
    if (obj.type == object_type) {
      /* Are there enough instances defined in the firmware? */
      if (obj.instances_minus_one >= instance) {
        return mxt_get_start_position(obj, instance);
      } else {
        mxt_warn(mxt->ctx, "T%u instance %u not present on device",
                 object_type, instance);
        return OBJECT_NOT_FOUND;
      }
    }
  }

  mxt_verb(mxt->ctx, "T%u not present on device", object_type);
  return OBJECT_NOT_FOUND;
}
Example #6
0
//******************************************************************************
/// \brief  Get messages (V2 interface)
/// \param  mxt Device context
/// \param  count Number of messages retrieved
/// \return #mxt_rc
int sysfs_get_msgs_v2(struct mxt_device *mxt, int *count)
{
  int num_bytes;
  uint16_t t5_size;
  char *filename;
  struct stat filestat;
  int ret;
  int fd;

  sysfs_reopen_notify_fd(mxt);

  filename = make_path(mxt, "debug_msg");

  ret = stat(filename, &filestat);
  if (ret < 0) {
    mxt_err(mxt->ctx, "Could not stat %s, error %s (%d)",
            filename, strerror(errno), errno);
    return mxt_errno_to_rc(errno);
  }

  mxt->sysfs.debug_v2_size = filestat.st_size;

  if (mxt->sysfs.debug_v2_msg_buf) {
    free(mxt->sysfs.debug_v2_msg_buf);
    mxt->sysfs.debug_v2_msg_buf = NULL;
  }

  mxt->sysfs.debug_v2_msg_buf = calloc(mxt->sysfs.debug_v2_size, sizeof(uint8_t));

  fd = open(filename, O_RDWR);
  if (fd < 0) {
    mxt_err(mxt->ctx, "Could not open %s, error %s (%d)", filename, strerror(errno), errno);
    ret = mxt_errno_to_rc(errno);
    goto close;
  }

  t5_size = mxt_get_object_size(mxt, GEN_MESSAGEPROCESSOR_T5) - 1;

  num_bytes = read(fd, mxt->sysfs.debug_v2_msg_buf, mxt->sysfs.debug_v2_size);
  if (num_bytes < 0) {
    mxt_err(mxt->ctx, "read error %s (%d)", strerror(errno), errno);
    ret = mxt_errno_to_rc(errno);
    goto close;
  }

  mxt->sysfs.debug_v2_msg_count = num_bytes / t5_size;
  mxt->sysfs.debug_v2_msg_ptr = 0;

  ret = MXT_SUCCESS;
  *count = mxt->sysfs.debug_v2_msg_count;
  mxt_verb(mxt->ctx, "count = %d", mxt->sysfs.debug_v2_msg_count);

close:
  close(fd);
  return ret;
}
Example #7
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);
}
Example #8
0
//******************************************************************************
/// \brief Read and deal with incoming command
/// \return #mxt_rc
static int handle_cmd(struct mxt_device *mxt, int sockfd)
{
  int ret;
  uint16_t address;
  uint16_t count;
  struct mxt_buffer linebuf;
  char *line;
  int offset;

  ret = mxt_buf_init(&linebuf);
  if (ret)
    return ret;

  ret = readline(mxt, sockfd, &linebuf);
  if (ret) {
    mxt_dbg(mxt->ctx, "Error reading or peer closed socket");
    goto free;
  }

  line = (char *)linebuf.data;
  if (strlen(line) == 0) {
    ret = MXT_SUCCESS;
    goto free;
  }

  mxt_verb(mxt->ctx, "%s", line);

  if (!strcmp(line, "SAT")) {
    mxt_info(mxt->ctx, "Server attached");
    ret = MXT_SUCCESS;
  } else if (!strcmp(line, "SDT")) {
    mxt_info(mxt->ctx, "Server detached");
    ret = MXT_SUCCESS;
  } else if (sscanf(line, "REA %" SCNu16 " %" SCNu16, &address, &count) == 2) {
    ret = bridge_rea_cmd(mxt, sockfd, address, count);
  } else if (sscanf(line, "WRI %" SCNu16 "%n", &address, &offset) == 1) {
    /* skip space */
    offset += 1;

    ret = bridge_wri_cmd(mxt, sockfd, address,
                         line + offset,
                         strlen(line) - offset);
  } else {
    mxt_info(mxt->ctx, "Unrecognised cmd \"%s\"", line);
    ret = MXT_SUCCESS;
  }

free:
  mxt_buf_free(&linebuf);
  return ret;
}
Example #9
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;
}
Example #10
0
//******************************************************************************
/// \brief  Discard all messages
/// \return #mxt_rc
int t44_msg_reset(struct mxt_device *mxt)
{
  int count, i, ret, size;
  unsigned char databuf[20];

  ret = t44_get_msg_count(mxt, &count);
  if (ret)
  {
    mxt_verb(mxt->ctx, "rc = %d", ret);
    return ret;
  }

  for (i = 0; i < count; i++)
  {
    ret = t44_get_msg_bytes(mxt, &databuf[0], sizeof(databuf), &size);
    if (ret)
    {
      mxt_verb(mxt->ctx, "rc = %d", ret);
      return ret;
    }
  }

  return MXT_SUCCESS;
}
Example #11
0
/*!
 * @brief  Populates a look-up table for the report IDs.
 * @return #mxt_rc
 */
int mxt_calc_report_ids(struct mxt_device *mxt)
{
  /* Report ID zero is reserved - start from one */
  int num_report_ids = 1;
  int report_id_count = 1;

  int i;
  int instance;
  int report_index;

  struct mxt_object obj;

  /* Calculate the number of report IDs */
  for (i = 0; i < mxt->info.id->num_objects; i++)
  {
    obj = mxt->info.objects[i];
    num_report_ids += MXT_INSTANCES(obj) * obj.num_report_ids;
  }

  /* Allocate memory for report ID look-up table */
  mxt->report_id_map = calloc(num_report_ids, sizeof(struct mxt_report_id_map));
  if (mxt->report_id_map == NULL)
  {
    mxt_err(mxt->ctx, "calloc failure");
    return MXT_ERROR_NO_MEM;
  }

  /* Store the object and instance for each report ID */
  for (i = 0; i < mxt->info.id->num_objects; i++)
  {
    obj = mxt->info.objects[i];

    for (instance = 0; instance < MXT_INSTANCES(obj); instance++)
    {
      for (report_index = 0; report_index < obj.num_report_ids; report_index++)
      {
        mxt->report_id_map[report_id_count].object_type = obj.type;
        mxt->report_id_map[report_id_count].instance = instance;
        report_id_count++;
      }
    }
  }

  mxt_verb(mxt->ctx, "Created a look-up table of %d Report IDs", report_id_count);

  return MXT_SUCCESS;
}
Example #12
0
//******************************************************************************
/// \brief  Handle status messages from the T68 Serial Data Command object
/// \return #mxt_rc
static int mxt_t68_get_status(struct mxt_device *mxt, uint8_t *msg,
                              void *context, uint8_t size)
{
  struct t68_ctx *ctx = context;
  unsigned int object_type = mxt_report_id_to_type(mxt, msg[0]);
  uint8_t status;

  mxt_verb(mxt->ctx, "Received message from T%u", object_type);

  if (object_type == SERIAL_DATA_COMMAND_T68) {
    /* mask off reserved bits */
    status = msg[1] & 0x0F;

    mxt_t68_print_status(ctx, status);

    return (status == 0) ? MXT_SUCCESS : MXT_ERROR_SERIAL_DATA_FAILURE;
  } else if (object_type == GEN_COMMANDPROCESSOR_T6) {
    print_t6_status(msg[1]);
  }
  return MXT_MSG_CONTINUE;
}
Example #13
0
//******************************************************************************
/// \brief Check status of previously sent command
/// \return #mxt_rc
static int mxt_self_cap_command(struct mxt_device *mxt, uint8_t *msg,
                                void *context, uint8_t size)
{
  unsigned int object_type = mxt_report_id_to_type(mxt, msg[0]);
  uint8_t *cmd = context;

  mxt_verb(mxt->ctx, "Received message from T%u", object_type);

  if (object_type == SPT_SELFCAPGLOBALCONFIG_T109) {
    if (msg[1] == *cmd) {
      switch (msg[2]) {
      case 0:
        return MXT_SUCCESS;
      case 1:
        return MXT_ERROR_SELFCAP_TUNE;
      }
    }
  } else if (object_type == GEN_COMMANDPROCESSOR_T6) {
    print_t6_status(msg[1]);
  }
  return MXT_MSG_CONTINUE;
}
Example #14
0
//******************************************************************************
/// \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;
}
Example #15
0
//******************************************************************************
/// \brief  Read registers from MXT chip, in blocks
/// \return #mxt_rc
int mxt_read_register(struct mxt_device *mxt, uint8_t *buf,
                      int start_register, size_t count)
{
  int ret;
  size_t received;
  size_t off = 0;

  mxt_verb(mxt->ctx, "%s start_register:%d count:%zu", __func__,
           start_register, count);

  while (off < count) {
    ret = mxt_read_register_block(mxt, buf + off, start_register + off,
                                  count - off, &received);
    if (ret)
      return ret;

    off += received;
  }

  mxt_log_buffer(mxt->ctx, LOG_VERBOSE, "RX:", buf, count);

  return MXT_SUCCESS;
}
Example #16
0
//******************************************************************************
/// \brief  Write register to MXT chip
/// \return #mxt_rc
int mxt_write_register(struct mxt_device *mxt, uint8_t const *buf,
                       int start_register, size_t count)
{
  int ret;

  mxt_verb(mxt->ctx, "%s start_register:%d count:%zu", __func__,
           start_register, count);

  switch (mxt->conn->type) {
  case E_SYSFS:
    ret = sysfs_write_register(mxt, buf, start_register, count);
    break;

  case E_I2C_DEV:
    ret = i2c_dev_write_register(mxt, buf, start_register, count);
    break;

#ifdef HAVE_LIBUSB
  case E_USB:
    ret = usb_write_register(mxt, buf, start_register, count);
    break;
#endif /* HAVE_LIBUSB */

  case E_HIDRAW:
    ret = hidraw_write_register(mxt, buf, start_register, count);
    break;

  default:
    mxt_err(mxt->ctx, "Device type not supported");
    ret = MXT_ERROR_NOT_SUPPORTED;
  }

  if (ret == MXT_SUCCESS)
    mxt_log_buffer(mxt->ctx, LOG_VERBOSE, "TX:", buf, count);

  return ret;
}
Example #17
0
//******************************************************************************
/// \brief  Get messages
/// \param  mxt  Maxtouch Device
/// \param  count Number of messages available
/// \param  init_timestamp Read newest dmesg line and initialise timestamp
/// \return #mxt_rc
int dmesg_get_msgs(struct mxt_device *mxt, int *count, bool init_timestamp)
{
  char msg[BUFFERSIZE];
  int ep, sp;
  int ret = MXT_SUCCESS;
  unsigned long sec, msec, lastsec = 0, lastmsec = 0;

  // Read entire kernel log buffer
  ep = klogctl(SYSLOG_ACTION_READ_ALL, mxt->sysfs.debug_msg_buf,
               mxt->sysfs.debug_msg_buf_size);
  // Return if no bytes read
  if (ep < 0) {
    mxt_warn(mxt->ctx, "klogctl error %d (%s)", errno, strerror(errno));
    ret = mxt_errno_to_rc(errno);
  } else {
    // null terminate
    mxt->sysfs.debug_msg_buf[ep] = 0;
    sp = ep;

    if (!init_timestamp)
      dmesg_list_empty(mxt);

    // Search for next new line character
    while (true) {
      sp--;
      while (sp >= 0 && *(mxt->sysfs.debug_msg_buf + sp) != '\n')
        sp--;

      if (sp <= 0)
        break;

      // Try to parse dmesg line
      if (sscanf(mxt->sysfs.debug_msg_buf+sp+1, "< %*c>[ %lu.%06lu] %255[^\n]",
                 &sec, &msec, msg) == 3) {
        if (init_timestamp) {
          mxt->sysfs.timestamp = sec;
          mxt->sysfs.mtimestamp = msec;
          mxt_verb(mxt->ctx, "%s - init [%5lu.%06lu]", __func__, sec, msec);
          break;
        }

        // Store time of last message in buffer
        if (lastsec == 0) {
          lastsec = sec;
          lastmsec = msec;
        }

        // Only 500 at a time, otherwise we overrun JNI reference limit.
        // Timestamp must be greater than previous messages, slightly
        // complicated by seconds and microseconds
        if ((mxt->sysfs.dmesg_count > MAX_DMESG_COUNT) ||
            (sec == mxt->sysfs.timestamp && msec <= mxt->sysfs.mtimestamp) ||
            (sec < mxt->sysfs.timestamp)) {
          mxt->sysfs.timestamp = lastsec;
          mxt->sysfs.mtimestamp = lastmsec;
          break;
        }

        char* msgptr;
        msg[sizeof(msg) - 1] = '\0';
        msgptr = strstr(msg, "MXT MSG");
        if (msgptr)
          dmesg_list_add(mxt, sec, msec, msgptr);
      }
    }

    if (!init_timestamp) {
      *count = mxt->sysfs.dmesg_count;
      mxt->sysfs.dmesg_ptr = mxt->sysfs.dmesg_head;
    }
  }

  return ret;
}
Example #18
0
//******************************************************************************
/// \brief Handle messages from the self test object
/// \return #mxt_rc
static int self_test_handle_messages(struct mxt_device *mxt)
{
   bool done = false;
   int count, i;
   time_t now;
   time_t start_time = time(NULL);
   static const uint8_t TIMEOUT = 10; // seconds
   uint8_t buf[10];
   int len;
   unsigned int object_type;
   int ret;

   while (!done)
   {
      mxt_msg_wait(mxt, 100);

      now = time(NULL);
      if ((now - start_time) > TIMEOUT)
      {
         mxt_err(mxt->ctx, "Timeout");
         return MXT_ERROR_TIMEOUT;
      }

      ret = mxt_get_msg_count(mxt, &count);
      if (ret)
        return ret;

      if (count > 0)
      {
         for (i = 0; i < count; i++)
         {
            ret = mxt_get_msg_bytes(mxt, buf, sizeof(buf), &len);
            if (ret)
              return ret;

            if (len > 0)
            {
               object_type = mxt_report_id_to_type(mxt, buf[0]);

               mxt_verb(mxt->ctx, "Received message from T%u", object_type);
               
               if (object_type == SPT_SELFTEST_T25)
               {
                  switch (buf[1])
                  {
                  case SELF_TEST_ALL:
                     mxt_info(mxt->ctx, "PASS: All tests passed");
                     ret = MXT_SUCCESS;
                     break;
                  case SELF_TEST_INVALID:
                     mxt_err(mxt->ctx, "FAIL: Invalid test command");
                     ret = MXT_ERROR_NOT_SUPPORTED;
                     break;
                  case SELF_TEST_TIMEOUT:
                     mxt_err(mxt->ctx, "FAIL: Test timeout");
                     ret = MXT_ERROR_TIMEOUT;
                     break;
                  case SELF_TEST_ANALOG:
                     mxt_err(mxt->ctx, "FAIL: AVdd Analog power is not present");
                     ret = MXT_ERROR_SELF_TEST_ANALOG;
                     break;
                  case SELF_TEST_PIN_FAULT:
                     mxt_err(mxt->ctx, "FAIL: Pin fault");
                     ret = MXT_ERROR_SELF_TEST_PIN_FAULT;
                     break;
                  case SELF_TEST_PIN_FAULT_2:
                     mxt_err(mxt->ctx, "FAIL: Pin fault 2");
                     ret = MXT_ERROR_SELF_TEST_PIN_FAULT;
                     break;
                  case SELF_TEST_AND_GATE:
                     mxt_err(mxt->ctx, "FAIL: AND Gate Fault");
                     ret = MXT_ERROR_SELF_TEST_AND_GATE;
                     break;
                  case SELF_TEST_SIGNAL_LIMIT:
                     mxt_err(mxt->ctx, "FAIL: Signal limit fault");
                     ret = MXT_ERROR_SELF_TEST_SIGNAL_LIMIT;
                     break;
                  case SELF_TEST_GAIN:
                     mxt_err(mxt->ctx, "FAIL: Gain error");
                     ret = MXT_ERROR_SELF_TEST_GAIN;
                     break;
                  default:
                     mxt_err(mxt->ctx, "Unrecognised status %02X", buf[1]);
                     ret = MXT_ERROR_UNEXPECTED_DEVICE_STATE;
                     break;
                  }

                  done = true;
               }
            }
         }
      }
   }

   return ret;
}
Example #19
0
//******************************************************************************
/// \brief Main function for mxt-app
int main (int argc, char *argv[])
{
  int ret;
  int c;
  int msgs_timeout = MSG_CONTINUOUS;
  bool msgs_enabled = false;
  uint8_t backup_cmd = BACKUPNV_COMMAND;
  unsigned char self_test_cmd = SELF_TEST_ALL;
  uint16_t address = 0;
  uint16_t count = 0;
  struct mxt_conn_info *conn = NULL;
  uint16_t object_type = 0;
  uint16_t msg_filter_type = 0;
  uint8_t instance = 0;
  uint8_t verbose = 2;
  uint16_t t37_frames = 1;
  uint8_t t37_mode = DELTAS_MODE;
  bool format = false;
  uint16_t port = 4000;
  uint8_t t68_datatype = 1;
  unsigned char databuf;
  char strbuf2[BUF_SIZE];
  char strbuf[BUF_SIZE];
  strbuf[0] = '\0';
  strbuf2[0] = '\0';
  mxt_app_cmd cmd = CMD_NONE;

  while (1) {
    int option_index = 0;

    static struct option long_options[] = {
      {"backup",           optional_argument, 0, 0},
      {"bootloader-version", no_argument,     0, 0},
      {"bridge-client",    required_argument, 0, 'C'},
      {"calibrate",        no_argument,       0, 0},
      {"checksum",         required_argument, 0, 0},
      {"debug-dump",       required_argument, 0, 0},
      {"device",           required_argument, 0, 'd'},
      {"t68-file",         required_argument, 0, 0},
      {"t68-datatype",     required_argument, 0, 0},
      {"msg-filter",       required_argument, 0, 'F'},
      {"format",           no_argument,       0, 'f'},
      {"flash",            required_argument, 0, 0},
      {"firmware-version", required_argument, 0, 0},
      {"frames",           required_argument, 0, 0},
      {"help",             no_argument,       0, 'h'},
      {"info",             no_argument,       0, 'i'},
      {"instance",         required_argument, 0, 'I'},
      {"load",             required_argument, 0, 0},
      {"save",             required_argument, 0, 0},
      {"messages",         optional_argument, 0, 'M'},
      {"count",            required_argument, 0, 'n'},
      {"port",             required_argument, 0, 'p'},
      {"query",            no_argument,       0, 'q'},
      {"read",             no_argument,       0, 'R'},
      {"reset",            no_argument,       0, 0},
      {"reset-bootloader", no_argument,       0, 0},
      {"register",         required_argument, 0, 'r'},
      {"references",       no_argument,       0, 0},
      {"self-cap-tune-config", no_argument,       0, 0},
      {"self-cap-tune-nvram",  no_argument,       0, 0},
      {"self-cap-signals", no_argument,       0, 0},
      {"self-cap-deltas",  no_argument,       0, 0},
      {"self-cap-refs",    no_argument,       0, 0},
      {"bridge-server",    no_argument,       0, 'S'},
      {"test",             optional_argument, 0, 't'},
      {"type",             required_argument, 0, 'T'},
      {"verbose",          required_argument, 0, 'v'},
      {"version",          no_argument,       0, 0},
      {"write",            no_argument,       0, 'W'},
      {"zero",             no_argument,       0, 0},
      {0,                  0,                 0,  0 }
    };

    c = getopt_long(argc, argv,
                    "C:d:D:fF:ghiI:M::m:n:p:qRr:St::T:v:W",
                    long_options, &option_index);
    if (c == -1)
      break;

    switch (c) {
    case 0:
      if (!strcmp(long_options[option_index].name, "t68-file")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_SERIAL_DATA;
          strncpy(strbuf, optarg, sizeof(strbuf));
          strbuf[sizeof(strbuf) - 1] = '\0';
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "t68-datatype")) {
        t68_datatype = strtol(optarg, NULL, 0);
      } else if (!strcmp(long_options[option_index].name, "flash")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_FLASH;
          strncpy(strbuf, optarg, sizeof(strbuf));
          strbuf[sizeof(strbuf) - 1] = '\0';
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "backup")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_BACKUP;
          if (optarg) {
            ret = mxt_convert_hex(optarg, &databuf, &count, sizeof(databuf));
            if (ret || count == 0) {
              fprintf(stderr, "Hex convert error\n");
              ret = MXT_ERROR_BAD_INPUT;
            }
            backup_cmd = databuf;
          }
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "calibrate")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_CALIBRATE;
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "debug-dump")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_DEBUG_DUMP;
          strncpy(strbuf, optarg, sizeof(strbuf));
          strbuf[sizeof(strbuf) - 1] = '\0';
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "reset")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_RESET;
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "self-cap-tune-config")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_SELF_CAP_TUNE_CONFIG;
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "self-cap-tune-nvram")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_SELF_CAP_TUNE_NVRAM;
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "load")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_LOAD_CFG;
          strncpy(strbuf, optarg, sizeof(strbuf));
          strbuf[sizeof(strbuf) - 1] = '\0';
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "save")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_SAVE_CFG;
          strncpy(strbuf, optarg, sizeof(strbuf));
          strbuf[sizeof(strbuf) - 1] = '\0';
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "reset-bootloader")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_RESET_BOOTLOADER;
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "bootloader-version")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_BOOTLOADER_VERSION;
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "checksum")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_CRC_CHECK;
          strncpy(strbuf, optarg, sizeof(strbuf));
          strbuf[sizeof(strbuf) - 1] = '\0';
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "zero")) {
        if (cmd == CMD_NONE) {
          cmd = CMD_ZERO_CFG;
        } else {
          print_usage(argv[0]);
          return MXT_ERROR_BAD_INPUT;
        }
      } else if (!strcmp(long_options[option_index].name, "firmware-version")) {
        strncpy(strbuf2, optarg, sizeof(strbuf2));
      } else if (!strcmp(long_options[option_index].name, "frames")) {
        t37_frames = strtol(optarg, NULL, 0);
      } else if (!strcmp(long_options[option_index].name, "references")) {
        t37_mode = REFS_MODE;
      } else if (!strcmp(long_options[option_index].name, "self-cap-signals")) {
        t37_mode = SELF_CAP_SIGNALS;
      } else if (!strcmp(long_options[option_index].name, "self-cap-refs")) {
        t37_mode = SELF_CAP_REFS;
      } else if (!strcmp(long_options[option_index].name, "self-cap-deltas")) {
        t37_mode = SELF_CAP_DELTAS;
      } else if (!strcmp(long_options[option_index].name, "version")) {
        printf("mxt-app %s%s\n", MXT_VERSION, ENABLE_DEBUG ? " DEBUG":"");
        return MXT_SUCCESS;
      } else {
        fprintf(stderr, "Unknown option %s\n",
                long_options[option_index].name);
      }
      break;

    case 'd':
      if (optarg) {
        if (!strncmp(optarg, "i2c-dev:", 8)) {
          ret = mxt_new_conn(&conn, E_I2C_DEV);
          if (ret)
            return ret;

          if (sscanf(optarg, "i2c-dev:%d-%x",
                     &conn->i2c_dev.adapter, &conn->i2c_dev.address) != 2) {
            fprintf(stderr, "Invalid device string %s\n", optarg);
            conn = mxt_unref_conn(conn);
            return MXT_ERROR_NO_MEM;
          }
        } else if (!strncmp(optarg, "sysfs:", 6)) {
          ret = mxt_new_conn(&conn, E_SYSFS);
          if (ret)
            return ret;

          conn->sysfs.path = (char *)calloc(strlen(optarg) + 1, sizeof(char));
          if (!conn->sysfs.path) {
            fprintf(stderr, "malloc failure\n");
            conn = mxt_unref_conn(conn);
            return MXT_ERROR_NO_MEM;
          }

          memcpy(conn->sysfs.path, optarg + 6, strlen(optarg) - 6);
        }
#ifdef HAVE_LIBUSB
        else if (!strncmp(optarg, "usb:", 4)) {
          ret = mxt_new_conn(&conn, E_USB);
          if (ret)
            return ret;

          if (sscanf(optarg, "usb:%d-%d", &conn->usb.bus, &conn->usb.device) != 2) {
            fprintf(stderr, "Invalid device string %s\n", optarg);
            conn = mxt_unref_conn(conn);
            return MXT_ERROR_NO_MEM;
          }
        }
#endif
        else if (!strncmp(optarg, "hidraw:", 7)) {
          ret = mxt_new_conn(&conn, E_HIDRAW);
          if (ret)
            return ret;

          conn->hidraw.report_id = HIDRAW_REPORT_ID;

          if (sscanf(optarg, "hidraw:%s", conn->hidraw.node) != 1) {
            fprintf(stderr, "Invalid device string %s\n", optarg);
            conn = mxt_unref_conn(conn);
            return MXT_ERROR_NO_MEM;
          }
        } else {
          fprintf(stderr, "Invalid device string %s\n", optarg);
          conn = mxt_unref_conn(conn);
          return MXT_ERROR_BAD_INPUT;
        }
      }
      break;

    case 'C':
      if (cmd == CMD_NONE) {
        cmd = CMD_BRIDGE_CLIENT;
        strncpy(strbuf, optarg, sizeof(strbuf));
        strbuf[sizeof(strbuf) - 1] = '\0';
      } else {
        print_usage(argv[0]);
        return MXT_ERROR_BAD_INPUT;
      }
      break;

    case 'g':
      if (cmd == CMD_NONE) {
        cmd = CMD_GOLDEN_REFERENCES;
      } else {
        print_usage(argv[0]);
        return MXT_ERROR_BAD_INPUT;
      }
      break;

    case 'h':
      print_usage(argv[0]);
      return MXT_SUCCESS;

    case 'f':
      format = true;
      break;

    case 'I':
      if (optarg) {
        instance = strtol(optarg, NULL, 0);
      }
      break;

    case 'M':
      msgs_enabled = true;
      if (cmd == CMD_NONE) {
        cmd = CMD_MESSAGES;
      }
      if (optarg)
        msgs_timeout = strtol(optarg, NULL, 0);
      break;

    case 'F':
      if (optarg) {
        msg_filter_type = strtol(optarg, NULL, 0);
      }
      break;

    case 'n':
      if (optarg) {
        count = strtol(optarg, NULL, 0);
      }
      break;

    case 'p':
      if (optarg) {
        port = strtol(optarg, NULL, 0);
      }
      break;

    case 'q':
      if (cmd == CMD_NONE) {
        cmd = CMD_QUERY;
      } else {
        print_usage(argv[0]);
        return MXT_ERROR_BAD_INPUT;
      }
      break;

    case 'r':
      if (optarg) {
        address = strtol(optarg, NULL, 0);
      }
      break;

    case 'R':
      if (cmd == CMD_NONE) {
        cmd = CMD_READ;
      } else {
        print_usage(argv[0]);
        return MXT_ERROR_BAD_INPUT;
      }
      break;

    case 'S':
      if (cmd == CMD_NONE) {
        cmd = CMD_BRIDGE_SERVER;
      } else {
        print_usage(argv[0]);
        return MXT_ERROR_BAD_INPUT;
      }
      break;

    case 'T':
      if (optarg) {
        object_type = strtol(optarg, NULL, 0);
      }
      break;

    case 'i':
      if (cmd == CMD_NONE) {
        cmd = CMD_INFO;
      } else {
        print_usage(argv[0]);
        return MXT_ERROR_BAD_INPUT;
      }
      break;

    case 't':
      if (cmd == CMD_NONE) {
        if (optarg) {
          ret = mxt_convert_hex(optarg, &databuf, &count, sizeof(databuf));
          if (ret) {
            fprintf(stderr, "Hex convert error\n");
            ret = MXT_ERROR_BAD_INPUT;
          } else {
            self_test_cmd = databuf;
          }
        }
        cmd = CMD_TEST;
      } else {
        print_usage(argv[0]);
        return MXT_ERROR_BAD_INPUT;
      }
      break;

    case 'v':
      if (optarg) {
        verbose = strtol(optarg, NULL, 0);
      }
      break;

    case 'W':
      if (cmd == CMD_NONE) {
        cmd = CMD_WRITE;
      } else {
        print_usage(argv[0]);
        return MXT_ERROR_BAD_INPUT;
      }
      break;

    default:
      /* Output newline to create space under getopt error output */
      fprintf(stderr, "\n\n");
      print_usage(argv[0]);
      return MXT_ERROR_BAD_INPUT;
    }
  }

  struct mxt_device *mxt = NULL;
  struct libmaxtouch_ctx *ctx;

  ret = mxt_new(&ctx);
  if (ret) {
    mxt_err(ctx, "Failed to init libmaxtouch");
    return ret;
  }

  /* Set debug level */
  mxt_set_log_level(ctx, verbose);
  mxt_verb(ctx, "verbose:%u", verbose);

  /* Debug does not work until mxt_set_verbose() is called */
  mxt_info(ctx, "Version:%s", MXT_VERSION);

  if (cmd == CMD_WRITE || cmd == CMD_READ) {
    mxt_verb(ctx, "instance:%u", instance);
    mxt_verb(ctx, "count:%u", count);
    mxt_verb(ctx, "address:%u", address);
    mxt_verb(ctx, "object_type:%u", object_type);
    mxt_verb(ctx, "format:%s", format ? "true" : "false");
  }

  if (cmd == CMD_QUERY) {
    ret = mxt_scan(ctx, &conn, true);
    goto free;

  } else if (cmd != CMD_FLASH && cmd != CMD_BOOTLOADER_VERSION) {
    ret = mxt_init_chip(ctx, &mxt, &conn);
    if (ret && cmd != CMD_CRC_CHECK )
      goto free;

    if (mxt)
      mxt_set_debug(mxt, true);
  }

  switch (cmd) {
  case CMD_WRITE:
    mxt_verb(ctx, "Write command");
    ret = mxt_handle_write_cmd(mxt, object_type, count, instance, address,
                               argc, argv);
    if (ret == MXT_ERROR_BAD_INPUT)
      goto free;
    break;

  case CMD_READ:
    mxt_verb(ctx, "Read command");
    ret = mxt_read_object(mxt, object_type, instance, address, count, format);
    break;

  case CMD_INFO:
    mxt_verb(ctx, "CMD_INFO");
    mxt_print_info_block(mxt);
    ret = MXT_SUCCESS;
    break;

  case CMD_GOLDEN_REFERENCES:
    mxt_verb(ctx, "CMD_GOLDEN_REFERENCES");
    ret = mxt_store_golden_refs(mxt);
    break;

  case CMD_BRIDGE_SERVER:
    mxt_verb(ctx, "CMD_BRIDGE_SERVER");
    mxt_verb(ctx, "port:%u", port);
    ret = mxt_socket_server(mxt, port);
    break;

  case CMD_BRIDGE_CLIENT:
    mxt_verb(ctx, "CMD_BRIDGE_CLIENT");
    ret = mxt_socket_client(mxt, strbuf, port);
    break;

  case CMD_SERIAL_DATA:
    mxt_verb(ctx, "CMD_SERIAL_DATA");
    mxt_verb(ctx, "t68_datatype:%u", t68_datatype);
    ret = mxt_serial_data_upload(mxt, strbuf, t68_datatype);
    break;

  case CMD_TEST:
    mxt_verb(ctx, "CMD_TEST");
    ret = run_self_tests(mxt, self_test_cmd);
    break;

  case CMD_FLASH:
    mxt_verb(ctx, "CMD_FLASH");
    ret = mxt_flash_firmware(ctx, mxt, strbuf, strbuf2, conn);
    break;

  case CMD_RESET:
    mxt_verb(ctx, "CMD_RESET");
    ret = mxt_reset_chip(mxt, false);
    break;

  case CMD_RESET_BOOTLOADER:
    mxt_verb(ctx, "CMD_RESET_BOOTLOADER");
    ret = mxt_reset_chip(mxt, true);
    break;

  case CMD_BOOTLOADER_VERSION:
    mxt_verb(ctx, "CMD_RESET_BOOTLOADER");
    ret = mxt_bootloader_version(ctx, mxt, conn);
    break;

  case CMD_MESSAGES:
    // Messages handled after switch
    break;

  case CMD_BACKUP:
    mxt_verb(ctx, "CMD_BACKUP");
    ret = mxt_backup_config(mxt, backup_cmd);
    break;

  case CMD_CALIBRATE:
    mxt_verb(ctx, "CMD_CALIBRATE");
    ret = mxt_calibrate_chip(mxt);
    break;

  case CMD_DEBUG_DUMP:
    mxt_verb(ctx, "CMD_DEBUG_DUMP");
    mxt_verb(ctx, "mode:%u", t37_mode);
    mxt_verb(ctx, "frames:%u", t37_frames);
    ret = mxt_debug_dump(mxt, t37_mode, strbuf, t37_frames);
    break;

  case CMD_ZERO_CFG:
    mxt_verb(ctx, "CMD_ZERO_CFG");
    ret = mxt_zero_config(mxt);
    if (ret)
      mxt_err(ctx, "Error zeroing all configuration settings");
    break;

  case CMD_LOAD_CFG:
    mxt_verb(ctx, "CMD_LOAD_CFG");
    mxt_verb(ctx, "filename:%s", strbuf);
    ret = mxt_load_config_file(mxt, strbuf);
    if (ret) {
      mxt_err(ctx, "Error loading the configuration");
    } else {
      mxt_info(ctx, "Configuration loaded");

      ret = mxt_backup_config(mxt, backup_cmd);
      if (ret) {
        mxt_err(ctx, "Error backing up");
      } else {
        mxt_info(ctx, "Configuration backed up");

        ret = mxt_reset_chip(mxt, false);
        if (ret) {
          mxt_err(ctx, "Error resetting");
        } else {
          mxt_info(ctx, "Chip reset");
        }
      }
    }
    break;

  case CMD_SAVE_CFG:
    mxt_verb(ctx, "CMD_SAVE_CFG");
    mxt_verb(ctx, "filename:%s", strbuf);
    ret = mxt_save_config_file(mxt, strbuf);
    break;

  case CMD_SELF_CAP_TUNE_CONFIG:
  case CMD_SELF_CAP_TUNE_NVRAM:
    mxt_verb(ctx, "CMD_SELF_CAP_TUNE");
    ret = mxt_self_cap_tune(mxt, cmd);
    break;

  case CMD_CRC_CHECK:
    mxt_verb(ctx, "CMD_CRC_CHECK");
    mxt_verb(ctx, "filename:%s", strbuf);
    ret = mxt_checkcrc(ctx, mxt, strbuf);
    break;

  case CMD_NONE:
  default:
    mxt_verb(ctx, "cmd: %d", cmd);
    mxt_set_log_fn(ctx, mxt_log_stdout);

    if (verbose <= 2)
      mxt_set_log_level(ctx, 2);

    ret = mxt_menu(mxt);
    break;
  }

  if (cmd == CMD_MESSAGES || (msgs_enabled && ret == MXT_SUCCESS)) {
    mxt_verb(ctx, "CMD_MESSAGES");
    mxt_verb(ctx, "msgs_timeout:%d", msgs_timeout);
    // Support message filtering with -T
    if (cmd == CMD_MESSAGES && !msg_filter_type)
      msg_filter_type = object_type;

    ret = print_raw_messages(mxt, msgs_timeout, msg_filter_type);
  }

  if (cmd != CMD_FLASH && cmd != CMD_BOOTLOADER_VERSION && mxt) {
    mxt_set_debug(mxt, false);
    mxt_free_device(mxt);
    mxt_unref_conn(conn);
  }

free:
  mxt_free(ctx);

  return ret;
}
Example #20
0
//******************************************************************************
/// \brief Check sysfs device directory for correct attributes
/// \return #mxt_rc
static int scan_sysfs_directory(struct libmaxtouch_ctx *ctx,
                                struct mxt_conn_info **conn,
                                struct dirent *i2c_dir,
                                const char *dirname,
                                bool acpi)
{
  char *pszDirname;
  size_t length;
  DIR *pDirectory;
  struct dirent *pEntry;
  bool mem_access_found = false;
  bool debug_found = false;
  bool debug_v2_found = false;
  int ret;

  length = strlen(dirname) + strlen(i2c_dir->d_name) + 2;

  if ((pszDirname = (char *)calloc(length, sizeof(char))) == NULL) {
    ret = MXT_ERROR_NO_MEM;
    goto free;
  }

  snprintf(pszDirname, length, "%s/%s", dirname, i2c_dir->d_name);

  pDirectory = opendir(pszDirname);
  if (!pDirectory) {
    ret = MXT_ERROR_NO_MEM;
    goto free;
  }

  while ((pEntry = readdir(pDirectory)) != NULL) {
    if (!strcmp(pEntry->d_name, "mem_access")) {
      mxt_dbg(ctx, "Found mem_access interface at %s/mem_access", pszDirname);
      mem_access_found = true;
    } else if (!strcmp(pEntry->d_name, "debug_enable")) {
      mxt_dbg(ctx, "Found debug_enable interface at %s/debug_enable", pszDirname);
      debug_found = true;
    } else if (!strcmp(pEntry->d_name, "debug_msg")) {
      mxt_dbg(ctx, "Found Debug V2 at %s/debug_msg", pszDirname);
      debug_v2_found = true;
    }
  }

  /* If device found, store it and return success */
  if (mem_access_found && (debug_found || debug_v2_found)) {
    ctx->scan_count++;

    if (ctx->query) {
      printf("sysfs:%s Atmel %s interface\n", pszDirname,
             debug_v2_found ? "Debug V2" : "Debug");
    } else {
      ret = sysfs_new_connection(ctx, conn, pszDirname, acpi);
      mxt_dbg(ctx, "Found %s", pszDirname);
      goto close;
    }
  } else {
    mxt_verb(ctx, "Ignoring %s", pszDirname);
  }

  ret = MXT_ERROR_NO_DEVICE;

close:
  (void)closedir(pDirectory);
free:
  free(pszDirname);

  return ret;
}
Example #21
0
/* Takes n = (degree+1) doubles, and fills in result with the n
 * coefficients of the polynomial that will fit them. */
bool ft_polyfit(struct libmaxtouch_ctx *ctx, double *xdata, double *ydata,
                double *result, int len)
{
  int k, j, i;
  int n = POLY_DEGREE + 1;
  double mat1[n * n];
  double mat2[n];
  double d;

  /* build input matrix - x values */
  for (i = 0; i < n; i++) {
    /* each matrix row */
    for (j = 0; j < n; j++) {
      mat1[i * n + j] = 0;

      /* each matrix col */
      for (k = 0; k < len; k++) {
        /* for each x value */
        mat1[i * n + j] += pow(xdata[k], (double)(i + j));
        mxt_verb(ctx, "i: %d j: %d k: %d, mat1[%d] = %0.2f",
            i, j, k, i * n + j, mat1[i * n + j]);
      }
    }
  }

  print_matrix(ctx, mat1, n);

  /* build & print resultant matrix - y values */
  mxt_verb(ctx, "\nResultant:");
  mat2[0] = 0;

  /* first row just the sum of y values */
  for (i = 0; i < len; i++)
    mat2[0] += ydata[i];

  mxt_verb(ctx, "mat2[0] = %0.2f", mat2[0]);

  for (i = 1; i < n; i++) {
    mat2[i] = 0;
    for (j = 0; j < len; j++)
      mat2[i] += ydata[j] * pow(xdata[j], i);

    mxt_verb(ctx, "mat2[%d] = %0.2f", i, mat2[i]);
  }

  /* Do Gauss-Jordan elimination on mat1. */
  for (i = 0; i < n; i++) {
    int lindex;
    double largest;
    /* choose largest pivot */
    for (j=i, largest = mat1[i * n + i], lindex = i; j < n; j++) {
      if (fabs(mat1[j * n + i]) > largest) {
        largest = fabs(mat1[j * n + i]);
        lindex = j;
      }
    }
    if (lindex != i) {
      /* swap rows i and lindex */
      for (k = 0; k < n; k++) {
        d = mat1[i * n + k];
        mat1[i * n + k] = mat1[lindex * n + k];
        mat1[lindex * n + k] = d;
      }
      d = mat2[i];
      mat2[i] = mat2[lindex];
      mat2[lindex] = d;
    }

    /* Make sure we have a non-zero pivot. */
    if (mat1[i * n + i] == 0.0) {
      /* this should be rotated. */
      mxt_err(ctx, "ERROR: Non-zero pivot");
      return false;
    }
    for (j = i + 1; j < n; j++) {
      d = mat1[j * n + i] / mat1[i * n + i];
      for (k = 0; k < n; k++)
        mat1[j * n + k] -= d * mat1[i * n + k];
      mat2[j] -= d * mat2[i];
    }
  }

  for (i = n - 1; i > 0; i--)
    for (j = i - 1; j >= 0; j--) {
      d = mat1[j * n + i] / mat1[i * n + i];
      for (k = 0; k < n; k++)
        mat1[j * n + k] -= d * mat1[i * n + k];
      mat2[j] -= d * mat2[i];
    }

  /* Now write the stuff into the result vector. */
  for (i = 0; i < n; i++) {
    result[i] = mat2[i] / mat1[i * n + i];
    mxt_verb(ctx, "coeff[%d] = %f", i, result[i]);
  }

  return true;
}
Example #22
0
//******************************************************************************
/// \brief  Read hex encoded data from file
/// \return #mxt_rc
static int mxt_t68_load_file(struct t68_ctx *ctx)
{
  int ret;
  uint8_t value = 0;
  FILE *fp;
  bool file_read = false;
  char buf[256];
  uint16_t hexcount;
  int c;

  /* open file */
  fp = fopen(ctx->filename, "r");
  if (fp == NULL) {
    mxt_err(ctx->lc, "Error opening %s", ctx->filename);
    return mxt_errno_to_rc(errno);
  }

  ret = mxt_buf_init(&ctx->buf);
  if (ret) {
    mxt_err(ctx->lc, "Error initialising buffer");
    goto close;
  }

  while (!file_read) {
    /* Read next value from file */
    c = getc(fp);
    if (c == EOF) {
      break;
    }
    /* skip spaces, newlines, commas*/
    else if (c == 0x20 || c == '\r' || c == '\n' || c == ',') {
      continue;
    }
    /* Ignore comment lines */
    else if (c == '[') {
      // Grab comment key
      if (fscanf(fp, "%255[^]]", buf) != 1) {
        ret = MXT_ERROR_FILE_FORMAT;
        goto fail;
      }

      mxt_verb(ctx->lc, "[%s]", buf);

      if (!strncasecmp(buf, "datatype=", 9)) {
        if (sscanf(buf + 9, "%d", &c) != 1) {
          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);
        }
      }

      // Read until end of line
      while (c != '\n') {
        c = getc(fp);
      }
      continue;
    }
    /* A value looks like "0xABu," */
    else if (c == '0') {
      if (fscanf(fp, "x%2su", (char *)&buf) != 1) {
        mxt_err(ctx->lc, "Parse error");
        ret = MXT_ERROR_FILE_FORMAT;
        goto fail;
      }

      ret = mxt_convert_hex(buf, &value, &hexcount, 3);
      if (ret)
        goto fail;

      ret = mxt_buf_add(&ctx->buf, value);
      if (ret)
        goto fail;
    } else {
      mxt_err(ctx->lc, "Unexpected character \"%c\"", c);
      ret = MXT_ERROR_FILE_FORMAT;
      goto fail;
    }
  }

  mxt_info(ctx->lc, "Loaded file %s, %zu bytes", ctx->filename, ctx->buf.size);

  return MXT_SUCCESS;

fail:
  mxt_buf_free(&ctx->buf);
close:
  fclose(fp);
  return ret;
}
Example #23
0
//******************************************************************************
/// \brief Read and deal with incoming command
/// \return #mxt_rc
static int handle_cmd(struct mxt_device *mxt, struct bridge_context *bridge_ctx)
{
  int ret;
  uint16_t address;
  uint16_t count;
  struct mxt_buffer linebuf;
  char *line;
  int offset;

  ret = mxt_buf_init(&linebuf);
  if (ret)
    return ret;

  ret = readline(mxt, bridge_ctx->sockfd, &linebuf);
  if (ret) {
    mxt_dbg(mxt->ctx, "Error reading or peer closed socket");
    goto free;
  }

  line = (char *)linebuf.data;
  if (strlen(line) == 0) {
    ret = MXT_SUCCESS;
    goto free;
  }

  mxt_verb(mxt->ctx, "%s", line);

  if (!strcmp(line, "SAT")) {
    mxt_info(mxt->ctx, "Server attached");
    ret = MXT_SUCCESS;
  } else if (!strcmp(line, "SDT")) {
    mxt_info(mxt->ctx, "Server detached");
    ret = MXT_SUCCESS;
  } else if (sscanf(line, "REA %" SCNu16 " %" SCNu16, &address, &count) == 2) {
    ret = bridge_rea_cmd(mxt, bridge_ctx, address, count);
  } else if (sscanf(line, "WRI %" SCNu16 "%n", &address, &offset) == 1) {
    /* skip space */
    offset += 1;

    ret = bridge_wri_cmd(mxt, bridge_ctx, address,
                         line + offset,
                         strlen(line) - offset);
  } else if (sscanf(line, "RST %" SCNu16 "%n", &address, &offset) == 1) {
    ret = bridge_handle_reset(mxt, bridge_ctx, address);
    ret = MXT_SUCCESS;
  } else if (sscanf(line, "MSGCFG %" SCNu16 "%n", &address, &offset) == 1) {
    mxt_info(mxt->ctx, "Configuring Messages");
    bridge_ctx->msgs_enabled = true;
    const char * const msg = "MSGCFG OK\n";

    ret = write(bridge_ctx->sockfd, msg, strlen(msg));
    if (ret < 0) {
      mxt_err(mxt->ctx, "Socket write error: %s (%d)", strerror(errno), errno);
      ret = mxt_errno_to_rc(errno);
    }
    ret = MXT_SUCCESS;
  } else {
    mxt_info(mxt->ctx, "Unrecognised cmd \"%s\"", line);
    ret = MXT_SUCCESS;
  }

free:
  mxt_buf_free(&linebuf);
  return ret;
}