Exemple #1
0
//******************************************************************************
/// \brief  Read boolean from file as ASCII 0/1
/// \param  mxt Device context
/// \param  filename Name of file to read
/// \param  value Value read from file
/// \return #mxt_rc
static int read_boolean_file(struct mxt_device *mxt, char *filename,
                             bool *value)
{
  FILE *file;
  char val;
  bool ret;

  file = fopen(filename, "r");
  if (!file) {
    mxt_err(mxt->ctx, "Could not open %s, error %s (%d)", filename, strerror(errno), errno);
    return mxt_errno_to_rc(errno);
  }

  ret = fread(&val, sizeof(char), 1, file);
  if (ret < 0) {
    mxt_err(mxt->ctx, "Error reading files");
    return MXT_ERROR_IO;
  }

  if (val == 49) { // ASCII '0'
    *value = true;
  } else {
    *value = false;
  }

  fclose(file);

  return MXT_SUCCESS;
}
Exemple #2
0
//******************************************************************************
/// \brief Initialize mXT device and read the info block
/// \return #mxt_rc
static int mxt_init_chip(struct libmaxtouch_ctx *ctx, struct mxt_device **mxt,
                         struct mxt_conn_info **conn)
{
  int ret;

  if (!*conn) {
    ret = mxt_scan(ctx, conn, false);
    if (ret == MXT_ERROR_NO_DEVICE) {
      mxt_err(ctx, "Unable to find a device");
      return ret;
    } else if (ret) {
      mxt_err(ctx, "Failed to find device");
      return ret;
    }
  }

  ret = mxt_new_device(ctx, *conn, mxt);
  if (ret)
    return ret;

#ifdef HAVE_LIBUSB
  if ((*mxt)->conn->type == E_USB && usb_is_bootloader(*mxt)) {
    mxt_free_device(*mxt);
    mxt_err(ctx, "USB device in bootloader mode");
    return MXT_ERROR_UNEXPECTED_DEVICE_STATE;
  }
#endif
  ret = mxt_get_info(*mxt);
  if (ret)
    return ret;

  return MXT_SUCCESS;
}
Exemple #3
0
//******************************************************************************
/// \brief Read MXT messages and send them to other end
/// \return #mxt_rc
static int handle_messages(struct mxt_device *mxt, int sockfd)
{
  int count, i;
  char *msg;
  int ret;

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

  if (count > 0) {
    for (i = 0; i < count; i++) {
      msg = mxt_get_msg_string(mxt);
      if (msg == NULL) {
        mxt_warn(mxt->ctx, "Failed to retrieve message");
        return MXT_SUCCESS;
      }

      ret = write(sockfd, msg, strlen(msg));
      if (ret < 0) {
        mxt_err(mxt->ctx, "Write failure: %s (%d)", strerror(errno), errno);
        return mxt_errno_to_rc(ret);
      }

      ret = write(sockfd, "\n", 1);
      if (ret < 0) {
        mxt_err(mxt->ctx, "Write failure: %s (%d)", strerror(errno), errno);
        return mxt_errno_to_rc(ret);
      }
    }
  }

  return MXT_SUCCESS;
}
Exemple #4
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;
}
Exemple #5
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;
}
/*!
 * @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;
}
Exemple #7
0
//******************************************************************************
/// \brief Open device
/// \return #mxt_rc
int mxt_new_device(struct libmaxtouch_ctx *ctx, struct mxt_conn_info *conn,
                   struct mxt_device **mxt)
{
  int ret;
  struct mxt_device *new_dev;

  new_dev = calloc(1, sizeof(struct mxt_device));
  if (!new_dev)
    return MXT_ERROR_NO_MEM;

  new_dev->ctx = ctx;
  new_dev->conn = mxt_ref_conn(conn);

  if (conn == NULL) {
    mxt_err(ctx, "New device connection parameters not valid");
    return MXT_ERROR_NO_DEVICE;
  }

  switch (conn->type) {
  case E_SYSFS:
    ret = sysfs_open(new_dev);
    break;

  case E_I2C_DEV:
    ret = i2c_dev_open(new_dev);
    break;

#ifdef HAVE_LIBUSB
  case E_USB:
    ret = usb_open(new_dev);
    break;
#endif /* HAVE_LIBUSB */

  case E_HIDRAW:
    ret = hidraw_register(new_dev);
    break;

  default:
    mxt_err(ctx, "Device type not supported");
    ret = MXT_ERROR_NOT_SUPPORTED;
    goto failure;
  }

  if (ret != 0)
    goto failure;

  *mxt = new_dev;
  return MXT_SUCCESS;

failure:
  mxt_unref_conn(conn);
  free(new_dev);
  return ret;
}
Exemple #8
0
//******************************************************************************
/// \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  Write register from MXT chip
/// \return #mxt_rc
int hidraw_write_register(struct mxt_device *mxt, unsigned char const *val, uint16_t start_register, int datalength)
{
  int ret;
  uint8_t byte_count;
  struct hid_packet write_pkt;
  memset(&write_pkt, 0x00, sizeof(struct hid_packet));

  write_pkt.report_id = mxt->conn->hidraw.report_id;
  write_pkt.cmd = 0x51;
  write_pkt.tx_bytes = 0;

  mxt_dbg(mxt->ctx, "%s - start_register:%d No. bytes to write:%d",
          __func__, start_register, datalength);

  ret = hidraw_open(mxt);
  if (ret)
    return ret;

  int bytes_written = 0;

  while (bytes_written < datalength) {
    write_pkt.rx_bytes = MXT_HID_ADDR_SIZE +
                         (datalength - bytes_written <= MXT_HID_WRITE_DATA_SIZE ? datalength - bytes_written : MXT_HID_WRITE_DATA_SIZE);
    write_pkt.address = htole16(start_register + bytes_written);
    memcpy(write_pkt.write_data, val + bytes_written, write_pkt.rx_bytes);

    ret =  hidraw_write_packet(mxt, &write_pkt, &byte_count);
    if (ret) {
      mxt_err(mxt->ctx, "read error %s (%d)", strerror(errno), errno);
      ret = mxt_errno_to_rc(errno);
      goto close;
    }
    bytes_written += byte_count;
    mxt_dbg(mxt->ctx, "Bytes Written:%d", bytes_written);

    struct hid_packet response_pkt;
    memset(&response_pkt, 0x00, sizeof(struct hid_packet));

    ret = hidraw_read_response(mxt, &response_pkt, 2);
    if (response_pkt.result != MXT_HID_READ_SUCCESS)
      mxt_err(mxt->ctx, "HIDRAW write failed: 0x%x",
              response_pkt.result);
  }

close:
  close(mxt->conn->hidraw.fd);
  mxt->conn->hidraw.fd = 0;
  return MXT_SUCCESS;
}
Exemple #10
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;
}
Exemple #11
0
//******************************************************************************
/// \brief  Close device
void mxt_free_device(struct mxt_device *mxt)
{
  switch (mxt->conn->type) {
  case E_SYSFS:
    sysfs_release(mxt);
    break;

  case E_I2C_DEV:
    i2c_dev_release(mxt);
    break;

#ifdef HAVE_LIBUSB
  case E_USB:
    usb_release(mxt);
    break;
#endif /* HAVE_LIBUSB */

  case E_HIDRAW:
    hidraw_release(mxt);
    break;

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


  mxt->conn = mxt_unref_conn(mxt->conn);

  free(mxt->info.raw_info);
  free(mxt->report_id_map);
  free(mxt);
}
Exemple #12
0
//******************************************************************************
/// \brief Insert page of data into buffer at appropriate co-ordinates
/// \return #mxt_rc
static int mxt_debug_insert_data(struct t37_ctx *ctx)
{
  int i;
  uint16_t value;
  int ofs;

  for (i = 0; i < ctx->page_size; i += 2) {
    if (ctx->x_ptr > ctx->x_size) {
      mxt_err(ctx->lc, "x pointer overrun");
      return MXT_INTERNAL_ERROR;
    }

    value = (ctx->t37_buf->data[i+1] << 8) | ctx->t37_buf->data[i];

    ofs = ctx->y_ptr + ctx->x_ptr * ctx->y_size;

    /* The last page may overlap the end of the matrix */
    if (ofs >= ctx->data_values)
      return MXT_SUCCESS;

    ctx->data_buf[ofs] = value;

    ctx->y_ptr++;

    if (ctx->y_ptr > ctx->stripe_endy) {
      ctx->y_ptr = ctx->stripe_starty;
      ctx->x_ptr++;
    }
  }

  return MXT_SUCCESS;
}
Exemple #13
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;
}
Exemple #14
0
//******************************************************************************
/// \brief  Enable/disable MSG retrieval
/// \return #mxt_rc
int mxt_set_debug(struct mxt_device *mxt, bool debug_state)
{
  int ret;

  switch (mxt->conn->type) {
  case E_SYSFS:
    ret = sysfs_set_debug(mxt, debug_state);
    break;

#ifdef HAVE_LIBUSB
  case E_USB:
#endif
  case E_I2C_DEV:
  case E_HIDRAW:
    /* No need to enable MSG output */
    ret = MXT_SUCCESS;
    break;

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

  return ret;
}
Exemple #15
0
//******************************************************************************
/// \brief  Read register from MXT chip
/// \return #mxt_rc
static int mxt_read_register_block(struct mxt_device *mxt, uint8_t *buf,
                                   int start_register, int count,
                                   size_t *bytes)
{
  int ret;

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

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

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

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

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

  return ret;
}
//******************************************************************************
/// \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;
  }
}
Exemple #17
0
//******************************************************************************
/// \brief  Get debug state
/// \param  mxt device context
/// \param  value true (debug enabled) or false (debug disabled)
/// \return #mxt_rc
int mxt_get_debug(struct mxt_device *mxt, bool *value)
{
  int ret;

  switch (mxt->conn->type) {
  case E_SYSFS:
    ret = sysfs_get_debug(mxt, value);
    break;

#ifdef HAVE_LIBUSB
  case E_USB:
    mxt_warn(mxt->ctx, "Kernel debug not supported for USB devices");
    ret = MXT_ERROR_NOT_SUPPORTED;
    break;
#endif /* HAVE_LIBUSB */

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

  return ret;
}
Exemple #18
0
//******************************************************************************
/// \brief  Get T5 message as string
/// \return Message string (null for no message)
char *mxt_get_msg_string(struct mxt_device *mxt)
{
  char *msg_string = NULL;

  switch (mxt->conn->type) {
  case E_SYSFS:
    if (sysfs_has_debug_v2(mxt))
      msg_string = sysfs_get_msg_string_v2(mxt);
    else
      msg_string = dmesg_get_msg_string(mxt);
    break;

#ifdef HAVE_LIBUSB
  case E_USB:
#endif /* HAVE_LIBUSB */
  case E_I2C_DEV:
  case E_HIDRAW:
    msg_string = t44_get_msg_string(mxt);
    break;

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

  if (msg_string)
    mxt_dbg(mxt->ctx, "%s", msg_string);

  return msg_string;
}
Exemple #19
0
//******************************************************************************
/// \brief  Wait for messages
int mxt_msg_wait(struct mxt_device *mxt, int timeout_ms)
{
  int ret;
  int fd = 0;
  int numfds = 0;
  struct pollfd fds[1];

  fd = mxt_get_msg_poll_fd(mxt);
  if (fd) {
    fds[0].fd = fd;
    fds[0].events = POLLPRI;
    numfds = 1;
  }

  ret = poll(fds, numfds, timeout_ms);
  if (ret == -1 && errno == EINTR) {
    mxt_dbg(mxt->ctx, "Interrupted");
    return MXT_ERROR_INTERRUPTED;
  } else if (ret < 0) {
    mxt_err(mxt->ctx, "poll returned %d (%s)", errno, strerror(errno));
    return MXT_ERROR_IO;
  }

  return MXT_SUCCESS;
}
Exemple #20
0
//******************************************************************************
/// \brief  Discard all previous messages
/// \return #mxt_rc
int mxt_msg_reset(struct mxt_device *mxt)
{
  int ret;

  switch (mxt->conn->type) {
  case E_SYSFS:
    if (sysfs_has_debug_v2(mxt))
      ret = sysfs_msg_reset_v2(mxt);
    else
      ret = dmesg_reset(mxt);

    break;

#ifdef HAVE_LIBUSB
  case E_USB:
#endif /* HAVE_LIBUSB */
  case E_I2C_DEV:
  case E_HIDRAW:
    ret = t44_msg_reset(mxt);
    break;

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

  return ret;
}
Exemple #21
0
//******************************************************************************
/// \brief  Get T5 message as byte array
/// \param  mxt  Maxtouch Device
/// \param  buf  Pointer to buffer
/// \param  buflen  Length of buffer
/// \param  count length of message in bytes
/// \return #mxt_rc
int mxt_get_msg_bytes(struct mxt_device *mxt, unsigned char *buf,
                      size_t buflen, int *count)
{
  int ret;

  switch (mxt->conn->type) {
  case E_SYSFS:
    if (sysfs_has_debug_v2(mxt))
      ret = sysfs_get_msg_bytes_v2(mxt, buf, buflen, count);
    else
      ret = dmesg_get_msg_bytes(mxt, buf, buflen, count);
    break;

#ifdef HAVE_LIBUSB
  case E_USB:
#endif /* HAVE_LIBUSB */
  case E_I2C_DEV:
  case E_HIDRAW:
    ret = t44_get_msg_bytes(mxt, buf, buflen, count);
    break;

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

  if (ret == MXT_SUCCESS)
    mxt_log_buffer(mxt->ctx, LOG_DEBUG, MSG_PREFIX, buf, *count);

  return ret;
}
Exemple #22
0
//******************************************************************************
/// \brief Read MXT messages and send them to other end
/// \return #mxt_rc
static int handle_messages(struct mxt_device *mxt, struct bridge_context *bridge_ctx)
{
  int msg_count, length;
  int ret;
  int i, j;

  unsigned char databuf[20];

  if (!bridge_ctx->msgs_enabled)
    return MXT_SUCCESS;

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

  for (i = 0; i < msg_count; i++) {
    int num_bytes;
    ret = mxt_get_msg_bytes(mxt, databuf, sizeof(databuf), &num_bytes);
    if (ret == MXT_ERROR_NO_MESSAGE)
      continue;
    else if (ret)
      return ret;

    length = snprintf(mxt->msg_string, sizeof(mxt->msg_string),
                      MXT_ADB_CLIENT_MSG_PREFIX);

    for (j = 0; j < num_bytes; j++) {
      length += snprintf(mxt->msg_string + length,
                         sizeof(mxt->msg_string) - length,
                         "%02X", databuf[j]);
    }

    ret = write(bridge_ctx->sockfd, mxt->msg_string, strlen(mxt->msg_string));
    if (ret < 0) {
      mxt_err(mxt->ctx, "Write failure: %s (%d)", strerror(errno), errno);
      return mxt_errno_to_rc(ret);
    }

    ret = write(bridge_ctx->sockfd, "\n", 1);
    if (ret < 0) {
      mxt_err(mxt->ctx, "Write failure: %s (%d)", strerror(errno), errno);
      return mxt_errno_to_rc(ret);
    }
  }

  return MXT_SUCCESS;
}
Exemple #23
0
//******************************************************************************
/// \brief Sets default function for SIGINT signal
static void mxt_release_sigint_handler(struct mxt_device *mxt, struct sigaction sa)
{
  sa.sa_handler = SIG_DFL;
  if (sigaction(SIGINT, &sa, NULL) == -1)
    mxt_err(mxt->ctx, "Can't return SIGINT to default handler");

  mxt_sigint_rx = 0;
}
Exemple #24
0
//******************************************************************************
/// \brief Handles SIGINT signal
static void mxt_init_sigint_handler(struct mxt_device *mxt, struct sigaction sa)
{
  sa.sa_handler = mxt_signal_handler;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_RESTART;
  if (sigaction(SIGINT, &sa, NULL) == -1)
    mxt_err(mxt->ctx, "Can't catch SIGINT");
}
Exemple #25
0
//******************************************************************************
/// \brief  Set debug state
/// \param  mxt Device context
/// \param  debug_state true = debug enabled, false = debug disabled
/// \return #mxt_rc
int sysfs_set_debug(struct mxt_device *mxt, bool debug_state)
{
  int ret;

  // Check device is initialised
  if (!mxt) {
    mxt_err(mxt->ctx, "Device uninitialised");
    return MXT_ERROR_NO_DEVICE;
  }

  if (mxt->sysfs.debug_v2 == true) {
    ret = write_boolean_file(mxt, make_path(mxt, "debug_v2_enable"), debug_state);
    if (ret)
      ret = write_boolean_file(mxt, make_path(mxt, "debug_enable"), debug_state);

    if (debug_state) {
      ret = sysfs_open_notify_fd(mxt);
      if (ret)
        return ret;
    } else {
      close(mxt->sysfs.debug_notify_fd);
    }
  } else {
    ret = MXT_SUCCESS;

    if (debug_state) {
      // Allocate buffer space
      mxt->sysfs.debug_msg_buf_size = dmesg_buf_size();
      mxt->sysfs.debug_msg_buf =
        (char *)calloc(mxt->sysfs.debug_msg_buf_size, sizeof(char));
      if (mxt->sysfs.debug_msg_buf == NULL) {
        mxt_err(mxt->ctx, "Error allocating memory for debug_msg_buf_size");
        ret = mxt_errno_to_rc(errno);
      }
    } else if (mxt->sysfs.debug_msg_buf) {
      // Free up the message buffer
      free(mxt->sysfs.debug_msg_buf);
      mxt->sysfs.debug_msg_buf = NULL;
    }

    if (ret == MXT_SUCCESS)
      ret = write_boolean_file(mxt, make_path(mxt, "debug_enable"), debug_state);
  }

  return ret;
}
Exemple #26
0
//******************************************************************************
/// \brief  Get sysfs directory
/// \param  mxt Device context
/// \return location of the sysfs interface files
char *sysfs_get_directory(struct mxt_device *mxt)
{
  // Check device is initialised
  if (!mxt) {
    mxt_err(mxt->ctx, "Device uninitialised");
    return 0;
  }

  return mxt->conn->sysfs.path;
}
Exemple #27
0
//******************************************************************************
/// \brief  Get debug state
/// \param  mxt Device context
/// \param  value true (debug enabled) or false (debug disabled)
/// \return #mxt_rc
int sysfs_get_debug(struct mxt_device *mxt, bool *value)
{
  // Check device is initialised
  if (!mxt) {
    mxt_err(mxt->ctx, "Device uninitialised");
    return false;
  }

  return read_boolean_file(mxt, make_path(mxt, "debug_enable"), value);
}
Exemple #28
0
/*!
 * @brief  Calculates and reports the Information Block Checksum.
 * @return #mxt_rc
 */
static int calculate_crc(struct mxt_device *mxt, uint32_t read_crc,
                         uint8_t *base_addr, size_t size)
{
  uint32_t calc_crc = 0; /* Checksum calculated by the driver code */
  uint16_t crc_byte_index = 0;

  /* Call the CRC function crc24() iteratively to calculate the CRC,
   * passing it two characters at a time.  */
  while (crc_byte_index < ((size % 2) ? (size - 1) : size))
  {
    calc_crc = crc24(calc_crc, *(base_addr + crc_byte_index),
                               *(base_addr + crc_byte_index + 1));
    crc_byte_index += 2;
  }

  /* Call crc24() for the final byte, plus an extra
   *  0 value byte to make the sequence even if it's odd */
  if (size % 2)
  {
    calc_crc = crc24(calc_crc, *(base_addr + crc_byte_index), 0);
  }

  /* Mask 32-bit calculated checksum to 24-bit */
  calc_crc &= calc_crc & 0x00FFFFFF;

  /* A zero CRC indicates a communications error */
  if (calc_crc == 0)
  {
    mxt_err(mxt->ctx, "Information Block Checksum zero");
    return MXT_ERROR_IO;
  }

  /* Compare the read checksum with calculated checksum */
  if (read_crc != calc_crc)
  {
    mxt_err(mxt->ctx, "Information Block Checksum error calc=%06X read=%06X",
        calc_crc, read_crc);
    return MXT_ERROR_INFO_CHECKSUM_MISMATCH;
  }

  mxt_dbg(mxt->ctx, "Information Block Checksum verified %06X", calc_crc);
  return MXT_SUCCESS;
}
Exemple #29
0
//******************************************************************************
/// \brief Handle bridge reset command
/// \return #mxt_rc
static int bridge_handle_reset(struct mxt_device *mxt,
                               struct bridge_context *bridge_ctx,
                               uint16_t address)
{
  int ret;
  char *response;
  const char * const PREFIX = "RST ";
  size_t response_len = 8;

  /* Allow for newline/null byte */
  response = calloc(response_len, sizeof(uint8_t));
  if (!response) {
    mxt_err(mxt->ctx, "Failed to allocate memory");
    ret = MXT_ERROR_NO_MEM;
    goto free;
  }

  strcpy(response, PREFIX);
  ret =  mxt_reset_chip(mxt, false);
  if (ret) {
    mxt_warn(mxt->ctx, "RST ERR");
    strcpy(response + strlen(PREFIX), "ERR\n");
    response_len = strlen(response);
  } else {
    mxt_info(mxt->ctx, "RST OK");
    strcpy(response + strlen(PREFIX), "OK\n");
    response_len = strlen(response);
  }

  ret = write(bridge_ctx->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);
  return ret;
}
Exemple #30
0
//******************************************************************************
/// \brief Allocate kernel log buffer
int dmesg_alloc_buffer(struct mxt_device *mxt)
{
  int size;

  size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, NULL, 0);
  if (size == -1) {
    mxt_err(mxt->ctx, "klogctl error %d (%s)", errno, strerror(errno));
    return mxt_errno_to_rc(errno);
  }

  // Allocate buffer space
  mxt->sysfs.debug_msg_buf_size = size;
  mxt->sysfs.debug_msg_buf = (char *)calloc(size, sizeof(char));
  if (mxt->sysfs.debug_msg_buf == NULL) {
    mxt_err(mxt->ctx, "Error allocating debug_msg_buf");
    return mxt_errno_to_rc(errno);
  }

  return 0;
}