//******************************************************************************
/// \brief  Read packet from MXT chip
/// \return #mxt_rc
static int hidraw_read_response(struct mxt_device *mxt, struct hid_packet *read_pkt,
                                size_t count)
{
  ssize_t ret = 0;
  size_t t_count = 0;
  int timeout = 0;

  do {
    ret = read(mxt->conn->hidraw.fd, read_pkt + t_count, count);
    if ((size_t)ret != count) {
      mxt_dbg(mxt->ctx, "Error %s (%d) reading from hidraw",
              strerror(errno), errno);
      ret = mxt_errno_to_rc(errno);
    } else {
      t_count += (size_t)ret;
    }
    usleep(HIDRAW_READ_RETRY_DELAY_US);
  } while (timeout++ <= HIDRAW_TIMEOUT_DELAY_US && t_count != count);

  mxt_dbg(mxt->ctx, "No. bytes requested: %zu, No. of bytes read: %zu",
          count, t_count);
  mxt_log_buffer(mxt->ctx, LOG_VERBOSE, "RD PKT RX:",
                 (const unsigned char *) read_pkt, count);
  return MXT_SUCCESS;
}
예제 #2
0
//******************************************************************************
/// \brief  Read register from MXT chip
/// \return #mxt_rc
int hidraw_read_register(struct mxt_device *mxt, unsigned char *buf, uint16_t start_register, int count)
{

  int ret;
  struct hid_packet read_pkt = { 0 };

  mxt_dbg(mxt->ctx, "%s - start_register:%d No. bytes requested:%d",
          __func__, start_register, count);

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

  int bytes_read = 0;
  while (bytes_read < count) {
    ret = hidraw_read_packet(mxt, &read_pkt,
                             start_register + bytes_read,
                             (count - bytes_read <= MXT_HID_READ_DATA_SIZE ? count - bytes_read : MXT_HID_READ_DATA_SIZE));
    if (ret < 0) {
      mxt_dbg(mxt->ctx, "read error %s (%d)", strerror(errno), errno);
      ret = mxt_errno_to_rc(errno);
    }

    memcpy(buf + bytes_read, read_pkt.read_data, ret);

    bytes_read += ret;
  }

  close(mxt->conn->hidraw.fd);
  mxt->conn->hidraw.fd = 0;
  return MXT_SUCCESS;
}
예제 #3
0
//******************************************************************************
/// \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;
}
예제 #4
0
//******************************************************************************
/// \brief Read one frame of diagnostic data
/// \return #mxt_rc
int mxt_read_diagnostic_data_frame(struct t37_ctx* ctx)
{
  int ret;

  /* iterate through stripes */
  for (ctx->pass = 0; ctx->pass < ctx->passes; ctx->pass++) {
    /* Calculate stripe parameters */
    ctx->stripe_starty = ctx->stripe_width * ctx->pass;
    ctx->stripe_endy = ctx->stripe_starty + ctx->stripe_width - 1;
    ctx->x_ptr = 0;
    ctx->y_ptr = ctx->stripe_starty;

    for (ctx->page = 0; ctx->page < ctx->pages_per_pass; ctx->page++) {
      mxt_dbg(ctx->lc, "Frame %d Pass %d Page %d", ctx->frame, ctx->pass,
              ctx->page);

      ret = mxt_get_t37_page(ctx);
      if (ret)
        return ret;

      mxt_debug_insert_data(ctx);
    }
  }

  return MXT_SUCCESS;
}
예제 #5
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;
}
예제 #6
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;
}
예제 #7
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;
}
예제 #8
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;
}
예제 #9
0
/*!
 * @brief  Logs information about the chip.
 */
void mxt_display_chip_info(struct mxt_device *mxt)
{
  struct mxt_object obj;
  char firmware_version[MXT_FW_VER_LEN];
  struct mxt_id_info *id = mxt->info.id;
  int i;

  mxt_get_firmware_version(mxt, (char *)&firmware_version);

  /* Display ID information */
  mxt_dbg(mxt->ctx, "Family ID = %u (0x%02X)",
          id->family, id->family);
  mxt_dbg(mxt->ctx, "Variant ID = %u (0x%02X)",
          id->variant, id->variant);
  mxt_dbg(mxt->ctx, "Firmware Version = %s", firmware_version);
  mxt_dbg(mxt->ctx, "Matrix X Size = %d", id->matrix_x_size);
  mxt_dbg(mxt->ctx, "Matrix Y Size = %d", id->matrix_y_size);
  mxt_dbg(mxt->ctx, "Number of elements in the Object Table = %d",
          id->num_objects);

  /* Display information about specific objects */
  for (i = 0; i < id->num_objects; i++) {
    obj = mxt->info.objects[i];

    mxt_dbg(mxt->ctx, "T%u size:%u instances:%u address:%u",
            obj.type, MXT_SIZE(obj),
            MXT_INSTANCES(obj), mxt_get_start_position(obj, 0));
  }
}
예제 #10
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));
}
예제 #11
0
파일: bridge.c 프로젝트: sonntam/obp-utils
//******************************************************************************
/// \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;
}
예제 #12
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;
}
예제 #13
0
//******************************************************************************
/// \brief  Write read command packet to MXT chip
/// \return #mxt_rc
static int hidraw_write_read_cmd(struct mxt_device *mxt, uint16_t start_register, uint8_t count, uint8_t *byte_count)
{
  struct hid_packet cmd_pkt = { 0 };

  cmd_pkt.report_id = mxt->conn->hidraw.report_id;
  cmd_pkt.cmd = 0x51;
  cmd_pkt.rx_bytes = 2;      /* includes start address word */
  cmd_pkt.tx_bytes = count;
  cmd_pkt.address = htole16(start_register);

  mxt_dbg(mxt->ctx, "Sending read command");

  return hidraw_write_packet(mxt, &cmd_pkt, byte_count);
}
예제 #14
0
//******************************************************************************
/// \brief  Open the hidraw dev interface and set the slave address
/// \return #mxt_rc
static int hidraw_open(struct mxt_device *mxt)
{
  char filename[20];

  snprintf(filename, sizeof(filename), "%s", mxt->conn->hidraw.node);
  mxt->conn->hidraw.fd = open(filename, O_RDWR|O_NONBLOCK);
  if (mxt->conn->hidraw.fd < 0) {
    mxt_err(mxt->ctx, "Could not open %s, error %s (%d)",
            filename, strerror(errno), errno);
    return mxt_errno_to_rc(errno);
  }
  mxt_dbg(mxt->ctx, "Opened %s, fd: %d", filename, mxt->conn->hidraw.fd);

  return MXT_SUCCESS;
}
예제 #15
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;
}
예제 #16
0
//******************************************************************************
/// \brief Read one frame of diagnostic data
/// \return #mxt_rc
static int mxt_read_diagnostic_data_self_cap(struct t37_ctx* ctx)
{
  int ret;

  for (ctx->pass = 0; ctx->pass < ctx->passes; ctx->pass++) {
    for (ctx->page = 0; ctx->page < ctx->pages_per_pass; ctx->page++) {
      mxt_dbg(ctx->lc, "Frame %d Pass %d Page %d", ctx->frame, ctx->pass,
              ctx->page);

      ret = mxt_get_t37_page(ctx);
      if (ret)
        return ret;

      mxt_debug_insert_data_self_cap(ctx);
    }
  }

  return MXT_SUCCESS;
}
예제 #17
0
//******************************************************************************
/// \brief Handle calibration messages
/// \return #mxt_rc
static int handle_calibrate_msg(struct mxt_device *mxt, uint8_t *msg,
                                void *context, uint8_t size)
{
  int *last_status = context;
  int status = msg[1];

  if (mxt_report_id_to_type(mxt, msg[0]) == GEN_COMMANDPROCESSOR_T6) {
    if (status & 0x10) {
      mxt_dbg(mxt->ctx, "Device calibrating");
    } else if (!(status & 0x10) && (*last_status & 0x10)) {
      mxt_info(mxt->ctx, "Device calibrated");
      return MXT_SUCCESS;
    }

    *last_status = status;
  }

  return MXT_MSG_CONTINUE;
}
예제 #18
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;
}
예제 #19
0
파일: bridge.c 프로젝트: sonntam/obp-utils
//******************************************************************************
/// \brief Main bridge function to handle a single connection
/// \return #mxt_rc
static int bridge(struct mxt_device *mxt, int sockfd)
{
  int ret, pollret;
  struct pollfd fds[2];
  int fopts = 0;
  int debug_ng_fd = 0;
  int numfds = 1;
  int timeout;

  mxt_info(mxt->ctx, "Connected");

  ret = mxt_msg_reset(mxt);
  if (ret)
    mxt_err(mxt->ctx, "Failure to reset msgs");

  fds[0].fd = sockfd;
  fds[0].events = POLLIN | POLLERR;

  ret = send_chip_attach(mxt, sockfd);
  if (ret)
    return ret;

  while (1) {
    debug_ng_fd = mxt_get_msg_poll_fd(mxt);
    if (debug_ng_fd) {
      fds[1].fd = debug_ng_fd;
      fds[1].events = POLLPRI;
      numfds = 2;
      timeout = -1;
    } else {
      timeout = 100; // milliseconds
    }

    pollret = poll(fds, numfds, timeout);
    if (pollret == -1 && errno == EINTR) {
      mxt_dbg(mxt->ctx, "Interrupted");
      continue;
    } else if (pollret == -1) {
      mxt_err(mxt->ctx, "Poll returned %d (%s)", errno, strerror(errno));
      ret = mxt_errno_to_rc(errno);
      goto disconnect;
    }

    /* Detect socket disconnect */
    if (fcntl(sockfd, F_GETFL, &fopts) < 0) {
      ret = MXT_SUCCESS;
      mxt_dbg(mxt->ctx, "Socket disconnected");
      goto disconnect;
    }

    if (fds[0].revents) {
      ret = handle_cmd(mxt, sockfd);
      if (ret) {
        mxt_dbg(mxt->ctx, "handle_cmd returned %d", ret);
        goto disconnect;
      }
    }

    /* If timeout or msg poll fd event */
    if (pollret == 0 || fds[1].revents) {
      ret = handle_messages(mxt, sockfd);
      if (ret)
        goto disconnect;
    }
  }

disconnect:
  mxt_info(mxt->ctx, "Disconnected");
  return ret;
}
예제 #20
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);
}
예제 #21
0
//******************************************************************************
/// \brief Initialise parameters and allocate buffers
/// \return #mxt_rc
int mxt_debug_dump_initialise(struct t37_ctx *ctx)
{
  struct mxt_id_info *id = ctx->mxt->info.id;
  int ret;

  ret = get_objects_addr(ctx);
  if (ret) {
    mxt_err(ctx->lc, "Failed to get object information");
    return ret;
  }

  mxt_dbg(ctx->lc, "t37_size: %d", ctx->t37_size);
  ctx->page_size = ctx->t37_size - 2;
  mxt_dbg(ctx->lc, "page_size: %d", ctx->page_size);

  switch (ctx->mode) {
  case DELTAS_MODE:
  case REFS_MODE:
    ctx->self_cap = false;

    if (id->family == 0xA0 && id->variant == 0x00) {
      /* mXT1386 data is formatted into stripes */
      ctx->x_size = 27;
      ctx->y_size = id->matrix_y_size;
      ctx->data_values = 27 * ctx->y_size;
      ctx->passes = 3;
      ctx->pages_per_pass = 8;
    } else {
      ctx->x_size = id->matrix_x_size;
      ctx->y_size = id->matrix_y_size;
      ctx->data_values = ctx->x_size * ctx->y_size;
      ctx->passes = 1;
      ctx->pages_per_pass = (ctx->data_values*2 + (ctx->page_size - 1)) /
                            ctx->page_size;
    }

    ctx->stripe_width = ctx->y_size / ctx->passes;
    mxt_dbg(ctx->lc, "stripe_width: %d", ctx->stripe_width);
    break;

  case SELF_CAP_SIGNALS:
  case SELF_CAP_DELTAS:
  case SELF_CAP_REFS:
    ctx->self_cap = true;

    if (id->family != 164) {
      mxt_err(ctx->lc, "Self cap data not available");
      return MXT_ERROR_NOT_SUPPORTED;
    }

    if (ctx->t111_instances == 0) {
      mxt_err(ctx->lc, "T111 not found");
      return MXT_ERROR_OBJECT_NOT_FOUND;
    }

    // read Ymax Y values, plus Ymax or 2Ymax X values
    ctx->passes = ctx->t111_instances;
    ctx->y_size = id->matrix_y_size;
    ctx->x_size = ctx->y_size * ((id->matrix_x_size > ctx->y_size) ? 2 : 1);
    ctx->data_values = (ctx->y_size + ctx->x_size) * ctx->passes;
    ctx->pages_per_pass = ((ctx->y_size + ctx->x_size)*sizeof(uint16_t) +(ctx->page_size - 1)) /
                          ctx->page_size;

    break;

  case AST_DELTAS:
  case AST_REFS:
    ctx->self_cap = false;
    ctx->active_stylus = true;

    if (id->family != 164) {
      mxt_err(ctx->lc, "active stylus data not available");
      return MXT_ERROR_NOT_SUPPORTED;
    }

    if (ctx->t107_instances == 0) {
      mxt_err(ctx->lc, "T107 not found");
      return MXT_ERROR_OBJECT_NOT_FOUND;
    }

    // read Ymax Y values, plus Ymax or 2Ymax X values
    ctx->passes = ctx->t107_instances;
    ctx->y_size = 2 * id->matrix_y_size;    // two scans per axis
    ctx->x_size = ctx->y_size * ((id->matrix_x_size > ctx->y_size) ? 2 : 1);
    ctx->data_values = (ctx->y_size + ctx->x_size) * ctx->passes;
    ctx->pages_per_pass = ((ctx->y_size + ctx->x_size)*sizeof(uint16_t) +(ctx->page_size - 1)) /
                          ctx->page_size;
    break;

  default:
    mxt_err(ctx->lc, "Unsupported mode %02X", ctx->mode);
    return MXT_INTERNAL_ERROR;
  }

  mxt_dbg(ctx->lc, "passes: %d", ctx->passes);
  mxt_dbg(ctx->lc, "pages_per_pass: %d", ctx->pages_per_pass);
  mxt_dbg(ctx->lc, "x_size: %d", ctx->x_size);
  mxt_dbg(ctx->lc, "y_size: %d", ctx->y_size);
  mxt_dbg(ctx->lc, "data_values: %d", ctx->data_values);

  /* allocate t37 buffers */
  ctx->t37_buf = (struct t37_diagnostic_data *)calloc(1, ctx->t37_size);
  if (!ctx->t37_buf) {
    mxt_err(ctx->lc, "calloc failure");
    return MXT_ERROR_NO_MEM;
  }

  /* allocate data buffer */
  ctx->data_buf = (uint16_t *)calloc(ctx->data_values, sizeof(uint16_t));
  if (!ctx->data_buf) {
    mxt_err(ctx->lc, "calloc failure");

    /* free other buffer in error path */
    free(ctx->t37_buf);
    ctx->t37_buf = NULL;
    return MXT_ERROR_NO_MEM;
  }

  return MXT_SUCCESS;
}
예제 #22
0
파일: bridge.c 프로젝트: sub77-bkp/mxt-app
//******************************************************************************
/// \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;
}