cregit-Linux how code gets into the kernel

Release 4.11 drivers/input/mouse/cyapa_gen5.c

/*
 * Cypress APA trackpad with I2C interface
 *
 * Author: Dudley Du <dudl@cypress.com>
 *
 * Copyright (C) 2014-2015 Cypress Semiconductor, Inc.
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file COPYING in the main directory of this archive for
 * more details.
 */

#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <linux/crc-itu-t.h>
#include <linux/pm_runtime.h>
#include "cyapa.h"


/* Macro of TSG firmware image */

#define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE      0x80

#define CYAPA_TSG_IMG_FW_HDR_SIZE           13

#define CYAPA_TSG_FW_ROW_SIZE               (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE)

#define CYAPA_TSG_IMG_START_ROW_NUM         0x002e

#define CYAPA_TSG_IMG_END_ROW_NUM           0x01fe

#define CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM 0x01ff

#define CYAPA_TSG_IMG_MAX_RECORDS           (CYAPA_TSG_IMG_END_ROW_NUM - \
                                CYAPA_TSG_IMG_START_ROW_NUM + 1 + 1)

#define CYAPA_TSG_IMG_READ_SIZE             (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE / 2)

#define CYAPA_TSG_START_OF_APPLICATION      0x1700

#define CYAPA_TSG_APP_INTEGRITY_SIZE        60

#define CYAPA_TSG_FLASH_MAP_METADATA_SIZE   60

#define CYAPA_TSG_BL_KEY_SIZE               8


#define CYAPA_TSG_MAX_CMD_SIZE              256

/* Macro of PIP interface */

#define PIP_BL_INITIATE_RESP_LEN            11

#define PIP_BL_FAIL_EXIT_RESP_LEN           11

#define PIP_BL_FAIL_EXIT_STATUS_CODE        0x0c

#define PIP_BL_VERIFY_INTEGRITY_RESP_LEN    12

#define PIP_BL_INTEGRITY_CHEKC_PASS         0x00

#define PIP_BL_BLOCK_WRITE_RESP_LEN         11


#define PIP_TOUCH_REPORT_ID         0x01

#define PIP_BTN_REPORT_ID           0x03

#define PIP_WAKEUP_EVENT_REPORT_ID  0x04

#define PIP_PUSH_BTN_REPORT_ID      0x06

#define GEN5_OLD_PUSH_BTN_REPORT_ID 0x05  
/* Special for old Gen5 TP. */

#define PIP_PROXIMITY_REPORT_ID     0x07


#define PIP_PROXIMITY_REPORT_SIZE	6

#define PIP_PROXIMITY_DISTANCE_OFFSET	0x05

#define PIP_PROXIMITY_DISTANCE_MASK	0x01


#define PIP_TOUCH_REPORT_HEAD_SIZE     7

#define PIP_TOUCH_REPORT_MAX_SIZE      127

#define PIP_BTN_REPORT_HEAD_SIZE       6

#define PIP_BTN_REPORT_MAX_SIZE        14

#define PIP_WAKEUP_EVENT_SIZE          4


#define PIP_NUMBER_OF_TOUCH_OFFSET  5

#define PIP_NUMBER_OF_TOUCH_MASK    0x1f

#define PIP_BUTTONS_OFFSET          5

#define PIP_BUTTONS_MASK            0x0f

#define PIP_GET_EVENT_ID(reg)       (((reg) >> 5) & 0x03)

#define PIP_GET_TOUCH_ID(reg)       ((reg) & 0x1f)

#define PIP_TOUCH_TYPE_FINGER	    0x00

#define PIP_TOUCH_TYPE_PROXIMITY    0x01

#define PIP_TOUCH_TYPE_HOVER	    0x02

#define PIP_GET_TOUCH_TYPE(reg)     ((reg) & 0x07)


#define RECORD_EVENT_NONE        0

#define RECORD_EVENT_TOUCHDOWN	 1

#define RECORD_EVENT_DISPLACE    2

#define RECORD_EVENT_LIFTOFF     3


#define PIP_SENSING_MODE_MUTUAL_CAP_FINE   0x00

#define PIP_SENSING_MODE_SELF_CAP          0x02


#define PIP_SET_PROXIMITY	0x49

/* Macro of Gen5 */

#define GEN5_BL_MAX_OUTPUT_LENGTH     0x0100

#define GEN5_APP_MAX_OUTPUT_LENGTH    0x00fe


#define GEN5_POWER_STATE_ACTIVE              0x01

#define GEN5_POWER_STATE_LOOK_FOR_TOUCH      0x02

#define GEN5_POWER_STATE_READY               0x03

#define GEN5_POWER_STATE_IDLE                0x04

#define GEN5_POWER_STATE_BTN_ONLY            0x05

#define GEN5_POWER_STATE_OFF                 0x06


#define GEN5_POWER_READY_MAX_INTRVL_TIME  50   
/* Unit: ms */

#define GEN5_POWER_IDLE_MAX_INTRVL_TIME   250  
/* Unit: ms */


#define GEN5_CMD_GET_PARAMETER		     0x05

#define GEN5_CMD_SET_PARAMETER		     0x06

#define GEN5_PARAMETER_ACT_INTERVL_ID        0x4d

#define GEN5_PARAMETER_ACT_INTERVL_SIZE      1

#define GEN5_PARAMETER_ACT_LFT_INTERVL_ID    0x4f

#define GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE  2

#define GEN5_PARAMETER_LP_INTRVL_ID          0x4c

#define GEN5_PARAMETER_LP_INTRVL_SIZE        2


#define GEN5_PARAMETER_DISABLE_PIP_REPORT    0x08


#define GEN5_BL_REPORT_DESCRIPTOR_SIZE            0x1d

#define GEN5_BL_REPORT_DESCRIPTOR_ID              0xfe

#define GEN5_APP_REPORT_DESCRIPTOR_SIZE           0xee

#define GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE  0xfa

#define GEN5_APP_REPORT_DESCRIPTOR_ID             0xf6


#define GEN5_RETRIEVE_MUTUAL_PWC_DATA        0x00

#define GEN5_RETRIEVE_SELF_CAP_PWC_DATA      0x01


#define GEN5_RETRIEVE_DATA_ELEMENT_SIZE_MASK 0x07


#define GEN5_CMD_EXECUTE_PANEL_SCAN          0x2a

#define GEN5_CMD_RETRIEVE_PANEL_SCAN         0x2b

#define GEN5_PANEL_SCAN_MUTUAL_RAW_DATA      0x00

#define GEN5_PANEL_SCAN_MUTUAL_BASELINE      0x01

#define GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT     0x02

#define GEN5_PANEL_SCAN_SELF_RAW_DATA        0x03

#define GEN5_PANEL_SCAN_SELF_BASELINE        0x04

#define GEN5_PANEL_SCAN_SELF_DIFFCOUNT       0x05

/* The offset only valid for retrieve PWC and panel scan commands */

#define GEN5_RESP_DATA_STRUCTURE_OFFSET      10

#define GEN5_PWC_DATA_ELEMENT_SIZE_MASK      0x07



struct cyapa_pip_touch_record {
	/*
         * Bit 7 - 3: reserved
         * Bit 2 - 0: touch type;
         *            0 : standard finger;
         *            1 : proximity (Start supported in Gen5 TP).
         *            2 : finger hover (defined, but not used yet.)
         *            3 - 15 : reserved.
         */
	
u8 touch_type;

	/*
         * Bit 7: indicates touch liftoff status.
         *              0 : touch is currently on the panel.
         *              1 : touch record indicates a liftoff.
         * Bit 6 - 5: indicates an event associated with this touch instance
         *              0 : no event
         *              1 : touchdown
         *              2 : significant displacement (> active distance)
         *              3 : liftoff (record reports last known coordinates)
         * Bit 4 - 0: An arbitrary ID tag associated with a finger
         *              to allow tracking a touch as it moves around the panel.
         */
	
u8 touch_tip_event_id;

	/* Bit 7 - 0 of X-axis coordinate of the touch in pixel. */
	
u8 x_lo;

	/* Bit 15 - 8 of X-axis coordinate of the touch in pixel. */
	
u8 x_hi;

	/* Bit 7 - 0 of Y-axis coordinate of the touch in pixel. */
	
u8 y_lo;

	/* Bit 15 - 8 of Y-axis coordinate of the touch in pixel. */
	
u8 y_hi;

	/*
         * The meaning of this value is different when touch_type is different.
         * For standard finger type:
         *      Touch intensity in counts, pressure value.
         * For proximity type (Start supported in Gen5 TP):
         *      The distance, in surface units, between the contact and
         *      the surface.
         **/
	
u8 z;

	/*
         * The length of the major axis of the ellipse of contact between
         * the finger and the panel (ABS_MT_TOUCH_MAJOR).
         */
	
u8 major_axis_len;

	/*
         * The length of the minor axis of the ellipse of contact between
         * the finger and the panel (ABS_MT_TOUCH_MINOR).
         */
	
u8 minor_axis_len;

	/*
         * The length of the major axis of the approaching tool.
         * (ABS_MT_WIDTH_MAJOR)
         */
	
u8 major_tool_len;

	/*
         * The length of the minor axis of the approaching tool.
         * (ABS_MT_WIDTH_MINOR)
         */
	
u8 minor_tool_len;

	/*
         * The angle between the panel vertical axis and
         * the major axis of the contact ellipse. This value is an 8-bit
         * signed integer. The range is -127 to +127 (corresponding to
         * -90 degree and +90 degree respectively).
         * The positive direction is clockwise from the vertical axis.
         * If the ellipse of contact degenerates into a circle,
         * orientation is reported as 0.
         */
	
u8 orientation;
} 
__packed;


struct cyapa_pip_report_data {
	
u8 report_head[PIP_TOUCH_REPORT_HEAD_SIZE];
	
struct cyapa_pip_touch_record touch_records[10];
} 
__packed;


struct cyapa_tsg_bin_image_head {
	
u8 head_size;  /* Unit: bytes, including itself. */
	
u8 ttda_driver_major_version;  /* Reserved as 0. */
	
u8 ttda_driver_minor_version;  /* Reserved as 0. */
	
u8 fw_major_version;
	
u8 fw_minor_version;
	
u8 fw_revision_control_number[8];
	
u8 silicon_id_hi;
	
u8 silicon_id_lo;
	
u8 chip_revision;
	
u8 family_id;
	
u8 bl_ver_maj;
	
u8 bl_ver_min;
} 
__packed;


struct cyapa_tsg_bin_image_data_record {
	
u8 flash_array_id;
	
__be16 row_number;
	/* The number of bytes of flash data contained in this record. */
	
__be16 record_len;
	/* The flash program data. */
	
u8 record_data[CYAPA_TSG_FW_ROW_SIZE];
} 
__packed;


struct cyapa_tsg_bin_image {
	
struct cyapa_tsg_bin_image_head image_head;
	
struct cyapa_tsg_bin_image_data_record records[0];
} 
__packed;


struct pip_bl_packet_start {
	
u8 sop;  /* Start of packet, must be 01h */
	
u8 cmd_code;
	
__le16 data_length;  /* Size of data parameter start from data[0] */
} 
__packed;


struct pip_bl_packet_end {
	
__le16 crc;
	
u8 eop;  /* End of packet, must be 17h */
} 
__packed;


struct pip_bl_cmd_head {
	
__le16 addr;   /* Output report register address, must be 0004h */
	/* Size of packet not including output report register address */
	
__le16 length;
	
u8 report_id;  /* Bootloader output report id, must be 40h */
	
u8 rsvd;  /* Reserved, must be 0 */
	
struct pip_bl_packet_start packet_start;
	
u8 data[0];  /* Command data variable based on commands */
} 
__packed;

/* Initiate bootload command data structure. */

struct pip_bl_initiate_cmd_data {
	/* Key must be "A5h 01h 02h 03h FFh FEh FDh 5Ah" */
	
u8 key[CYAPA_TSG_BL_KEY_SIZE];
	
u8 metadata_raw_parameter[CYAPA_TSG_FLASH_MAP_METADATA_SIZE];
	
__le16 metadata_crc;
} 
__packed;


struct tsg_bl_metadata_row_params {
	
__le16 size;
	
__le16 maximum_size;
	
__le32 app_start;
	
__le16 app_len;
	
__le16 app_crc;
	
__le32 app_entry;
	
__le32 upgrade_start;
	
__le16 upgrade_len;
	
__le16 entry_row_crc;
	
u8 padding[36];  /* Padding data must be 0 */
	
__le16 metadata_crc;  /* CRC starts at offset of 60 */
} 
__packed;

/* Bootload program and verify row command data structure */

struct tsg_bl_flash_row_head {
	
u8 flash_array_id;
	
__le16 flash_row_id;
	
u8 flash_data[0];
} 
__packed;


struct pip_app_cmd_head {
	
__le16 addr;   /* Output report register address, must be 0004h */
	/* Size of packet not including output report register address */
	
__le16 length;
	
u8 report_id;  /* Application output report id, must be 2Fh */
	
u8 rsvd;  /* Reserved, must be 0 */
	/*
         * Bit 7: reserved, must be 0.
         * Bit 6-0: command code.
         */
	
u8 cmd_code;
	
u8 parameter_data[0];  /* Parameter data variable based on cmd_code */
} 
__packed;

/* Application get/set parameter command data structure */

struct gen5_app_set_parameter_data {
	
u8 parameter_id;
	
u8 parameter_size;
	
__le32 value;
} 
__packed;


struct gen5_app_get_parameter_data {
	
u8 parameter_id;
} 
__packed;


struct gen5_retrieve_panel_scan_data {
	
__le16 read_offset;
	
__le16 read_elements;
	
u8 data_id;
} 
__packed;


u8 pip_read_sys_info[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x02 };

u8 pip_bl_read_app_info[] = { 0x04, 0x00, 0x0b, 0x00, 0x40, 0x00,
		0x01, 0x3c, 0x00, 0x00, 0xb0, 0x42, 0x17
	};


static u8 cyapa_pip_bl_cmd_key[] = { 0xa5, 0x01, 0x02, 0x03,
	0xff, 0xfe, 0xfd, 0x5a };

static int cyapa_pip_event_process(struct cyapa *cyapa,
				   struct cyapa_pip_report_data *report_data);


int cyapa_pip_cmd_state_initialize(struct cyapa *cyapa) { struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; init_completion(&pip->cmd_ready); atomic_set(&pip->cmd_issued, 0); mutex_init(&pip->cmd_lock); mutex_init(&pip->pm_stage_lock); pip->pm_stage = CYAPA_PM_DEACTIVE; pip->resp_sort_func = NULL; pip->in_progress_cmd = PIP_INVALID_CMD; pip->resp_data = NULL; pip->resp_len = NULL; cyapa->dev_pwr_mode = UNINIT_PWR_MODE; cyapa->dev_sleep_time = UNINIT_SLEEP_TIME; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du101100.00%3100.00%
Total101100.00%3100.00%

/* Return negative errno, or else the number of bytes read. */
ssize_t cyapa_i2c_pip_read(struct cyapa *cyapa, u8 *buf, size_t size) { int ret; if (size == 0) return 0; if (!buf || size > CYAPA_REG_MAP_SIZE) return -EINVAL; ret = i2c_master_recv(cyapa->client, buf, size); if (ret != size) return (ret < 0) ? ret : -EIO; return size; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du76100.00%1100.00%
Total76100.00%1100.00%

/** * Return a negative errno code else zero on success. */
ssize_t cyapa_i2c_pip_write(struct cyapa *cyapa, u8 *buf, size_t size) { int ret; if (!buf || !size) return -EINVAL; ret = i2c_master_send(cyapa->client, buf, size); if (ret != size) return (ret < 0) ? ret : -EIO; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du66100.00%1100.00%
Total66100.00%1100.00%


static void cyapa_set_pip_pm_state(struct cyapa *cyapa, enum cyapa_pm_stage pm_stage) { struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; mutex_lock(&pip->pm_stage_lock); pip->pm_stage = pm_stage; mutex_unlock(&pip->pm_stage_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du49100.00%1100.00%
Total49100.00%1100.00%


static void cyapa_reset_pip_pm_state(struct cyapa *cyapa) { struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; /* Indicates the pip->pm_stage is not valid. */ mutex_lock(&pip->pm_stage_lock); pip->pm_stage = CYAPA_PM_DEACTIVE; mutex_unlock(&pip->pm_stage_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du46100.00%1100.00%
Total46100.00%1100.00%


static enum cyapa_pm_stage cyapa_get_pip_pm_state(struct cyapa *cyapa) { struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; enum cyapa_pm_stage pm_stage; mutex_lock(&pip->pm_stage_lock); pm_stage = pip->pm_stage; mutex_unlock(&pip->pm_stage_lock); return pm_stage; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du53100.00%1100.00%
Total53100.00%1100.00%

/** * This function is aimed to dump all not read data in Gen5 trackpad * before send any command, otherwise, the interrupt line will be blocked. */
int cyapa_empty_pip_output_data(struct cyapa *cyapa, u8 *buf, int *len, cb_sort func) { struct input_dev *input = cyapa->input; struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; enum cyapa_pm_stage pm_stage = cyapa_get_pip_pm_state(cyapa); int length; int report_count; int empty_count; int buf_len; int error; buf_len = 0; if (len) { buf_len = (*len < CYAPA_REG_MAP_SIZE) ? *len : CYAPA_REG_MAP_SIZE; *len = 0; } report_count = 8; /* max 7 pending data before command response data */ empty_count = 0; do { /* * Depending on testing in cyapa driver, there are max 5 "02 00" * packets between two valid buffered data report in firmware. * So in order to dump all buffered data out and * make interrupt line release for reassert again, * we must set the empty_count check value bigger than 5 to * make it work. Otherwise, in some situation, * the interrupt line may unable to reactive again, * which will cause trackpad device unable to * report data any more. * for example, it may happen in EFT and ESD testing. */ if (empty_count > 5) return 0; error = cyapa_i2c_pip_read(cyapa, pip->empty_buf, PIP_RESP_LENGTH_SIZE); if (error < 0) return error; length = get_unaligned_le16(pip->empty_buf); if (length == PIP_RESP_LENGTH_SIZE) { empty_count++; continue; } else if (length > CYAPA_REG_MAP_SIZE) { /* Should not happen */ return -EINVAL; } else if (length == 0) { /* Application or bootloader launch data polled out. */ length = PIP_RESP_LENGTH_SIZE; if (buf && buf_len && func && func(cyapa, pip->empty_buf, length)) { length = min(buf_len, length); memcpy(buf, pip->empty_buf, length); *len = length; /* Response found, success. */ return 0; } continue; } error = cyapa_i2c_pip_read(cyapa, pip->empty_buf, length); if (error < 0) return error; report_count--; empty_count = 0; length = get_unaligned_le16(pip->empty_buf); if (length <= PIP_RESP_LENGTH_SIZE) { empty_count++; } else if (buf && buf_len && func && func(cyapa, pip->empty_buf, length)) { length = min(buf_len, length); memcpy(buf, pip->empty_buf, length); *len = length; /* Response found, success. */ return 0; } else if (cyapa->operational && input && input->users && (pm_stage == CYAPA_PM_RUNTIME_RESUME || pm_stage == CYAPA_PM_RUNTIME_SUSPEND)) { /* Parse the data and report it if it's valid. */ cyapa_pip_event_process(cyapa, (struct cyapa_pip_report_data *)pip->empty_buf); } error = -EINVAL; } while (report_count); return error; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du392100.00%3100.00%
Total392100.00%3100.00%


static int cyapa_do_i2c_pip_cmd_irq_sync( struct cyapa *cyapa, u8 *cmd, size_t cmd_len, unsigned long timeout) { struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; int error; /* Wait for interrupt to set ready completion */ init_completion(&pip->cmd_ready); atomic_inc(&pip->cmd_issued); error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len); if (error) { atomic_dec(&pip->cmd_issued); return (error < 0) ? error : -EIO; } /* Wait for interrupt to indicate command is completed. */ timeout = wait_for_completion_timeout(&pip->cmd_ready, msecs_to_jiffies(timeout)); if (timeout == 0) { atomic_dec(&pip->cmd_issued); return -ETIMEDOUT; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du130100.00%2100.00%
Total130100.00%2100.00%


static int cyapa_do_i2c_pip_cmd_polling( struct cyapa *cyapa, u8 *cmd, size_t cmd_len, u8 *resp_data, int *resp_len, unsigned long timeout, cb_sort func) { struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; int tries; int length; int error; atomic_inc(&pip->cmd_issued); error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len); if (error) { atomic_dec(&pip->cmd_issued); return error < 0 ? error : -EIO; } length = resp_len ? *resp_len : 0; if (resp_data && resp_len && length != 0 && func) { tries = timeout / 5; do { usleep_range(3000, 5000); *resp_len = length; error = cyapa_empty_pip_output_data(cyapa, resp_data, resp_len, func); if (error || *resp_len == 0) continue; else break; } while (--tries > 0); if ((error || *resp_len == 0) || tries <= 0) error = error ? error : -ETIMEDOUT; } atomic_dec(&pip->cmd_issued); return error; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du209100.00%2100.00%
Total209100.00%2100.00%


int cyapa_i2c_pip_cmd_irq_sync( struct cyapa *cyapa, u8 *cmd, int cmd_len, u8 *resp_data, int *resp_len, unsigned long timeout, cb_sort func, bool irq_mode) { struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; int error; if (!cmd || !cmd_len) return -EINVAL; /* Commands must be serialized. */ error = mutex_lock_interruptible(&pip->cmd_lock); if (error) return error; pip->resp_sort_func = func; pip->resp_data = resp_data; pip->resp_len = resp_len; if (cmd_len >= PIP_MIN_APP_CMD_LENGTH && cmd[4] == PIP_APP_CMD_REPORT_ID) { /* Application command */ pip->in_progress_cmd = cmd[6] & 0x7f; } else if (cmd_len >= PIP_MIN_BL_CMD_LENGTH && cmd[4] == PIP_BL_CMD_REPORT_ID) { /* Bootloader command */ pip->in_progress_cmd = cmd[7]; } /* Send command data, wait and read output response data's length. */ if (irq_mode) { pip->is_irq_mode = true; error = cyapa_do_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len, timeout); if (error == -ETIMEDOUT && resp_data && resp_len && *resp_len != 0 && func) { /* * For some old version, there was no interrupt for * the command response data, so need to poll here * to try to get the response data. */ error = cyapa_empty_pip_output_data(cyapa, resp_data, resp_len, func); if (error || *resp_len == 0) error = error ? error : -ETIMEDOUT; } } else { pip->is_irq_mode = false; error = cyapa_do_i2c_pip_cmd_polling(cyapa, cmd, cmd_len, resp_data, resp_len, timeout, func); } pip->resp_sort_func = NULL; pip->resp_data = NULL; pip->resp_len = NULL; pip->in_progress_cmd = PIP_INVALID_CMD; mutex_unlock(&pip->cmd_lock); return error; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du292100.00%2100.00%
Total292100.00%2100.00%


bool cyapa_sort_tsg_pip_bl_resp_data(struct cyapa *cyapa, u8 *data, int len) { if (!data || len < PIP_MIN_BL_RESP_LENGTH) return false; /* Bootloader input report id 30h */ if (data[PIP_RESP_REPORT_ID_OFFSET] == PIP_BL_RESP_REPORT_ID && data[PIP_RESP_RSVD_OFFSET] == PIP_RESP_RSVD_KEY && data[PIP_RESP_BL_SOP_OFFSET] == PIP_SOP_KEY) return true; return false; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du59100.00%2100.00%
Total59100.00%2100.00%


bool cyapa_sort_tsg_pip_app_resp_data(struct cyapa *cyapa, u8 *data, int len) { struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; int resp_len; if (!data || len < PIP_MIN_APP_RESP_LENGTH) return false; if (data[PIP_RESP_REPORT_ID_OFFSET] == PIP_APP_RESP_REPORT_ID && data[PIP_RESP_RSVD_OFFSET] == PIP_RESP_RSVD_KEY) { resp_len = get_unaligned_le16(&data[PIP_RESP_LENGTH_OFFSET]); if (GET_PIP_CMD_CODE(data[PIP_RESP_APP_CMD_OFFSET]) == 0x00 && resp_len == PIP_UNSUPPORTED_CMD_RESP_LENGTH && data[5] == pip->in_progress_cmd) { /* Unsupported command code */ return false; } else if (GET_PIP_CMD_CODE(data[PIP_RESP_APP_CMD_OFFSET]) == pip->in_progress_cmd) { /* Correct command response received */ return true; } } return false; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du128100.00%2100.00%
Total128100.00%2100.00%


static bool cyapa_sort_pip_application_launch_data(struct cyapa *cyapa, u8 *buf, int len) { if (buf == NULL || len < PIP_RESP_LENGTH_SIZE) return false; /* * After reset or power on, trackpad device always sets to 0x00 0x00 * to indicate a reset or power on event. */ if (buf[0] == 0 && buf[1] == 0) return true; return false; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du54100.00%3100.00%
Total54100.00%3100.00%


static bool cyapa_sort_gen5_hid_descriptor_data(struct cyapa *cyapa, u8 *buf, int len) { int resp_len; int max_output_len; /* Check hid descriptor. */ if (len != PIP_HID_DESCRIPTOR_SIZE) return false; resp_len = get_unaligned_le16(&buf[PIP_RESP_LENGTH_OFFSET]); max_output_len = get_unaligned_le16(&buf[16]); if (resp_len == PIP_HID_DESCRIPTOR_SIZE) { if (buf[PIP_RESP_REPORT_ID_OFFSET] == PIP_HID_BL_REPORT_ID && max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) { /* BL mode HID Descriptor */ return true; } else if ((buf[PIP_RESP_REPORT_ID_OFFSET] == PIP_HID_APP_REPORT_ID) && max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) { /* APP mode HID Descriptor */ return true; } } return false; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du108100.00%3100.00%
Total108100.00%3100.00%


static bool cyapa_sort_pip_deep_sleep_data(struct cyapa *cyapa, u8 *buf, int len) { if (len == PIP_DEEP_SLEEP_RESP_LENGTH && buf[PIP_RESP_REPORT_ID_OFFSET] == PIP_APP_DEEP_SLEEP_REPORT_ID && (buf[4] & PIP_DEEP_SLEEP_OPCODE_MASK) == PIP_DEEP_SLEEP_OPCODE) return true; return false; }

Contributors

PersonTokensPropCommitsCommitProp
Dudley Du48100.00%2100.00%
Total48100.00%2100.00%


static int gen5_idle_state_parse(struct cyapa *cyapa) { u8 resp_data[PIP_HID_DESCRIPTOR_SIZE]; int max_output_len; int length; u8 cmd[2]; int ret; int error; /* * Dump all buffered data firstly for the situation * when the trackpad is just power on the cyapa go here. */ cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); memset(resp_data, 0, sizeof(resp_data)); ret = cyapa_i2c_pip_read(cyapa, resp_data, 3); if (ret != 3) return ret < 0 ? ret : -EIO; length = get_unaligned_le16(&resp_data[PIP_RESP_LENGTH_OFFSET]); if (length == PIP_RESP_LENGTH_SIZE) { /* Normal state of Gen5 with no data to response */ cyapa->gen