//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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); }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; } }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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"); }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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); }
/*! * @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; }
//****************************************************************************** /// \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; }
//****************************************************************************** /// \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; }