From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4FDFDC433FE for ; Wed, 22 Dec 2021 12:46:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240902AbhLVMqT (ORCPT ); Wed, 22 Dec 2021 07:46:19 -0500 Received: from new3-smtp.messagingengine.com ([66.111.4.229]:46945 "EHLO new3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237086AbhLVMqR (ORCPT ); Wed, 22 Dec 2021 07:46:17 -0500 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailnew.nyi.internal (Postfix) with ESMTP id AFFFD5803DA; Wed, 22 Dec 2021 07:46:16 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Wed, 22 Dec 2021 07:46:16 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alistair23.me; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; s=fm2; bh= BlYqeqemM2kH0tviP1iG5/7ttzsJ4yS4sPMdY5h7Gxc=; b=gPLylzwMNCOv2hLF C4PgfPtHBpopxACSozmIoatyAqcw/ClSw9RxOG4NCt4wIrT011rzGkQGqlU9HIBs wCM/M+xWS1wL6XO4p2b5FQGwEwmfzpztx/wCSW5IF1vff8zA553RmuJEJQy+oHq5 gW8lMxFdf4XmgBxOcEuJ0lizOmw58Dj5PW7KeODBdK4yjUDkLsqPhP+raHF9cqNF 2Ftdb8uEjliUPvsPoOVMtipyW8MFWzmB/N7zqOllG7DgQgQrpcyiLcWOaKrMF3mS 3RG0R9Jb6JsWD8Hh5873p5/M01jCS9eraP4/gx9n5axMP+O3p6QPXHgccOL0vQdu LafwxA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm1; bh=BlYqeqemM2kH0tviP1iG5/7ttzsJ4yS4sPMdY5h7G xc=; b=jnScgZ4GHW7ZN6E88WCUh0VyEm4BSnCMCzorFBGGgVJwXawGG1pCcen/0 oZ2ceTNe86NOZW7ObFMDud8ZTnGm3z3vQZvkqMwDHURiZT4ncN7de2Aqv6mma8vt xzNLVYOfbIF7KuHAQHYfkO2SpbQ18FUtpFPHOCs1CN8egPCiGrw5hHNsmxIPDJSi Na8xjolEevlPGFKjwnuuDFsBynO/4uuRegGv2s4E8VXqwHyDSgehqkOty1QAiyCC Ne1gwJmMX/zCD29uFdFt9fkc3EYkgD9n2PtlM9HWOkdDEOFUlCTpE0jAg6QNQ/4E FgW0YALfYRKNpf9rMSiGRVF7GpaIg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvuddruddtiedgfeejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfgggtgfesthekredtredtjeenucfhrhhomheptehlihhs thgrihhrucfhrhgrnhgtihhsuceorghlihhsthgrihhrsegrlhhishhtrghirhdvfedrmh gvqeenucggtffrrghtthgvrhhnpeejfeethfefudefgeffkefgueffgeefteefgfffheeg lefgvddvheevtdeuueejjeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmh grihhlfhhrohhmpegrlhhishhtrghirhesrghlihhsthgrihhrvdefrdhmvg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 22 Dec 2021 07:46:12 -0500 (EST) From: Alistair Francis To: devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org Cc: dmitry.torokhov@gmail.com, alistair23@gmail.com, robh+dt@kernel.org, linus.walleij@linaro.org, rydberg@bitmath.org, andreas@kemnade.info, =?UTF-8?q?Myl=C3=A8ne=20Josserand?= , Maxime Ripard , Alistair Francis Subject: [PATCH v4 1/4] Input: Add driver for Cypress Generation 5 touchscreen Date: Wed, 22 Dec 2021 22:46:00 +1000 Message-Id: <20211222124603.326920-2-alistair@alistair23.me> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211222124603.326920-1-alistair@alistair23.me> References: <20211222124603.326920-1-alistair@alistair23.me> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Mylène Josserand This is the basic driver for the Cypress TrueTouch Gen5 touchscreen controllers. This driver supports only the I2C bus but it uses regmap so SPI support could be added later. The touchscreen can retrieve some defined zone that are handled as buttons (according to the hardware). That is why it handles button and multitouch events. Reviewed-by: Maxime Ripard Signed-off-by: Mylène Josserand Signed-off-by: Alistair Francis --- drivers/input/touchscreen/Kconfig | 14 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/cyttsp5.c | 922 ++++++++++++++++++++++++++++ 3 files changed, 937 insertions(+) create mode 100644 drivers/input/touchscreen/cyttsp5.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 2f6adfb7b938..61f0452050f6 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -284,6 +284,20 @@ config TOUCHSCREEN_CYTTSP4_SPI To compile this driver as a module, choose M here: the module will be called cyttsp4_spi. +config TOUCHSCREEN_CYTTSP5 + tristate "Cypress TrueTouch Gen5 Touchscreen Driver" + depends on OF && I2C + select REGMAP_I2C + select CRC_ITU_T + help + Driver for Parade TrueTouch Standard Product + Generation 5 touchscreen controllers. + I2C bus interface support only. + Say Y here if you have a Cypress Gen5 touchscreen. + If unsure, say N. + To compile this driver as a module, choose M here: the + module will be called cyttsp5. + config TOUCHSCREEN_DA9034 tristate "Touchscreen support for Dialog Semiconductor DA9034" depends on PMIC_DA903X diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 39a8127cf6a5..0ea5c47f7fd9 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_CORE) += cyttsp4_core.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_I2C) += cyttsp4_i2c.o cyttsp_i2c_common.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_SPI) += cyttsp4_spi.o +obj-$(CONFIG_TOUCHSCREEN_CYTTSP5) += cyttsp5.o obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c new file mode 100644 index 000000000000..f0d1fa27e17e --- /dev/null +++ b/drivers/input/touchscreen/cyttsp5.c @@ -0,0 +1,922 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Parade TrueTouch(TM) Standard Product V5 Module. + * + * Copyright (C) 2015 Parade Technologies + * Copyright (C) 2012-2015 Cypress Semiconductor + * Copyright (C) 2018 Bootlin + * + * Authors: Mylène Josserand + * Alistair Francis + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CYTTSP5_NAME "cyttsp5" +#define CY_I2C_DATA_SIZE (2 * 256) +#define HID_VERSION 0x0100 +#define CY_MAX_INPUT 512 +#define CYTTSP5_PREALLOCATED_CMD_BUFFER 32 +#define CY_BITS_PER_BTN 1 +#define CY_NUM_BTN_EVENT_ID ((1 << CY_BITS_PER_BTN) - 1) + +#define MAX_AREA 255 +#define HID_OUTPUT_BL_SOP 0x1 +#define HID_OUTPUT_BL_EOP 0x17 +#define HID_OUTPUT_BL_LAUNCH_APP 0x3B +#define HID_OUTPUT_BL_LAUNCH_APP_SIZE 11 +#define HID_OUTPUT_GET_SYSINFO 0x2 +#define HID_OUTPUT_GET_SYSINFO_SIZE 5 +#define HID_OUTPUT_MAX_CMD_SIZE 12 + +#define HID_DESC_REG 0x1 +#define HID_INPUT_REG 0x3 +#define HID_OUTPUT_REG 0x4 + +#define REPORT_ID_TOUCH 0x1 +#define REPORT_ID_BTN 0x3 +#define REPORT_SIZE_5 5 +#define REPORT_SIZE_8 8 +#define REPORT_SIZE_16 16 + +/* Touch reports offsets */ +/* Header offsets */ +#define TOUCH_REPORT_DESC_HDR_CONTACTCOUNT 16 +/* Record offsets */ +#define TOUCH_REPORT_DESC_CONTACTID 8 +#define TOUCH_REPORT_DESC_X 16 +#define TOUCH_REPORT_DESC_Y 32 +#define TOUCH_REPORT_DESC_P 48 +#define TOUCH_REPORT_DESC_MAJ 56 +#define TOUCH_REPORT_DESC_MIN 64 + +/* HID */ +#define HID_TOUCH_REPORT_ID 0x1 +#define HID_BTN_REPORT_ID 0x3 +#define HID_APP_RESPONSE_REPORT_ID 0x1F +#define HID_APP_OUTPUT_REPORT_ID 0x2F +#define HID_BL_RESPONSE_REPORT_ID 0x30 +#define HID_BL_OUTPUT_REPORT_ID 0x40 + +#define HID_OUTPUT_RESPONSE_REPORT_OFFSET 2 +#define HID_OUTPUT_RESPONSE_CMD_OFFSET 4 +#define HID_OUTPUT_RESPONSE_CMD_MASK 0x7F + +#define HID_SYSINFO_SENSING_OFFSET 33 +#define HID_SYSINFO_BTN_OFFSET 48 +#define HID_SYSINFO_BTN_MASK 0xFF +#define HID_SYSINFO_MAX_BTN 8 + +/* Timeout in ms */ +#define CY_HID_OUTPUT_TIMEOUT 200 +#define CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT 3000 +#define CY_HID_GET_HID_DESCRIPTOR_TIMEOUT 4000 + +/* maximum number of concurrent tracks */ +#define TOUCH_REPORT_SIZE 10 +#define TOUCH_INPUT_HEADER_SIZE 7 +#define BTN_REPORT_SIZE 9 +#define BTN_INPUT_HEADER_SIZE 5 + +#define MAX_CY_TCH_T_IDS 32 + +/* All usage pages for Touch Report */ +#define TOUCH_REPORT_USAGE_PG_X 0x00010030 +#define TOUCH_REPORT_USAGE_PG_Y 0x00010031 +#define TOUCH_REPORT_USAGE_PG_P 0x000D0030 +#define TOUCH_REPORT_USAGE_PG_CONTACTID 0x000D0051 +#define TOUCH_REPORT_USAGE_PG_CONTACTCOUNT 0x000D0054 +#define TOUCH_REPORT_USAGE_PG_MAJ 0xFF010062 +#define TOUCH_REPORT_USAGE_PG_MIN 0xFF010063 +#define TOUCH_COL_USAGE_PG 0x000D0022 + +/* helpers */ +#define HI_BYTE(x) ((u8)(((x) >> 8) & 0xFF)) +#define LOW_BYTE(x) ((u8)((x) & 0xFF)) + +/* System Information interface definitions */ +struct cyttsp5_sensing_conf_data_dev { + u8 electrodes_x; + u8 electrodes_y; + __le16 len_x; + __le16 len_y; + __le16 res_x; + __le16 res_y; + __le16 max_z; + u8 origin_x; + u8 origin_y; + u8 btn; + u8 scan_mode; + u8 max_num_of_tch_per_refresh_cycle; +} __packed; + +struct cyttsp5_sensing_conf_data { + u16 res_x; + u16 res_y; + u16 max_z; + u16 len_x; + u16 len_y; + u8 origin_x; + u8 origin_y; + u8 max_tch; +}; + +enum cyttsp5_tch_abs { /* for ordering within the extracted touch data array */ + CY_TCH_X, /* X */ + CY_TCH_Y, /* Y */ + CY_TCH_P, /* P (Z) */ + CY_TCH_T, /* TOUCH ID */ + CY_TCH_MAJ, /* TOUCH_MAJOR */ + CY_TCH_MIN, /* TOUCH_MINOR */ + CY_TCH_NUM_ABS, +}; + +struct cyttsp5_tch_abs_params { + size_t ofs; /* abs byte offset */ + size_t size; /* size in bits */ + size_t min; /* min value */ + size_t max; /* max value */ + size_t bofs; /* bit offset */ +}; + +struct cyttsp5_touch { + int abs[CY_TCH_NUM_ABS]; +}; + +struct cyttsp5_sysinfo { + struct cyttsp5_sensing_conf_data sensing_conf_data; + int num_btns; + struct cyttsp5_tch_abs_params tch_hdr; + struct cyttsp5_tch_abs_params tch_abs[CY_TCH_NUM_ABS]; + u32 key_code[HID_SYSINFO_MAX_BTN]; +}; + +struct cyttsp5_hid_desc { + __le16 hid_desc_len; + u8 packet_id; + u8 reserved_byte; + __le16 bcd_version; + __le16 report_desc_len; + __le16 report_desc_register; + __le16 input_register; + __le16 max_input_len; + __le16 output_register; + __le16 max_output_len; + __le16 command_register; + __le16 data_register; + __le16 vendor_id; + __le16 product_id; + __le16 version_id; + u8 reserved[4]; +} __packed; + +struct cyttsp5 { + struct device *dev; + struct completion cmd_done; + struct cyttsp5_sysinfo sysinfo; + struct cyttsp5_hid_desc hid_desc; + u8 cmd_buf[CYTTSP5_PREALLOCATED_CMD_BUFFER]; + u8 input_buf[CY_MAX_INPUT]; + u8 response_buf[CY_MAX_INPUT]; + struct gpio_desc *reset_gpio; + struct input_dev *input; + char phys[NAME_MAX]; + int num_prv_rec; + struct regmap *regmap; + struct touchscreen_properties prop; + struct regulator *vdd; +}; + +/* + * For what understood in the datasheet, the register does not + * matter. For consistency, used the Input Register address + * but it does mean anything to the device. The important data + * to send is the I2C address + */ +static int cyttsp5_read(struct cyttsp5 *ts, u8 *buf, u32 max) +{ + int error; + u32 size; + u8 temp[2]; + + /* Read the frame to retrieve the size */ + error = regmap_bulk_read(ts->regmap, HID_INPUT_REG, temp, sizeof(temp)); + if (error) + return error; + + size = get_unaligned_le16(temp); + if (!size || size == 2) + return 0; + + if (size > max) + return -EINVAL; + + /* Get the real value */ + return regmap_bulk_read(ts->regmap, HID_INPUT_REG, buf, size); +} + +static int cyttsp5_write(struct cyttsp5 *ts, unsigned int reg, u8 *data, + size_t size) +{ + u8 cmd[HID_OUTPUT_MAX_CMD_SIZE]; + + if (size + 1 > HID_OUTPUT_MAX_CMD_SIZE) + return -E2BIG; + + /* High bytes of register address needed as first byte of cmd */ + cmd[0] = HI_BYTE(reg); + + /* Copy the rest of the data */ + if (data) + memcpy(&cmd[1], data, size); + + /* The hardware wants to receive a frame with the address register + * contains in the first two bytes. As the regmap_write function + * add the register adresse in the frame, we use the LOW_BYTE as + * first frame byte for the address register and the first + * data byte is the high register + left of the cmd to send + */ + return regmap_bulk_write(ts->regmap, LOW_BYTE(reg), cmd, size + 1); +} + +static void cyttsp5_get_touch_axis(int *axis, int size, int max, u8 *xy_data, + int bofs) +{ + int nbyte; + + for (nbyte = 0, *axis = 0; nbyte < size; nbyte++) + *axis = *axis + ((xy_data[nbyte] >> bofs) << (nbyte * 8)); + + *axis &= max - 1; +} + +static void cyttsp5_get_touch_record(struct cyttsp5 *ts, + struct cyttsp5_touch *touch, u8 *xy_data) +{ + struct cyttsp5_sysinfo *si = &ts->sysinfo; + enum cyttsp5_tch_abs abs; + + for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) + cyttsp5_get_touch_axis(&touch->abs[abs], + si->tch_abs[abs].size, + si->tch_abs[abs].max, + xy_data + si->tch_abs[abs].ofs, + si->tch_abs[abs].bofs); +} + +static void cyttsp5_get_mt_touches(struct cyttsp5 *ts, + struct cyttsp5_touch *tch, int num_cur_tch) +{ + struct cyttsp5_sysinfo *si = &ts->sysinfo; + int i, t = 0, offset = 0; + DECLARE_BITMAP(ids, MAX_CY_TCH_T_IDS); + u8 *tch_addr; + int tmp; + + bitmap_zero(ids, MAX_CY_TCH_T_IDS); + memset(tch->abs, 0, sizeof(tch->abs)); + + switch (ts->input_buf[2]) { + case HID_TOUCH_REPORT_ID: + offset = TOUCH_INPUT_HEADER_SIZE; + break; + case HID_BTN_REPORT_ID: + offset = BTN_INPUT_HEADER_SIZE; + break; + } + + for (i = 0; i < num_cur_tch; i++) { + tch_addr = ts->input_buf + offset + (i * TOUCH_REPORT_SIZE); + cyttsp5_get_touch_record(ts, tch, tch_addr); + + /* Convert MAJOR/MINOR from mm to resolution */ + tmp = tch->abs[CY_TCH_MAJ] * 100 * si->sensing_conf_data.res_x; + tch->abs[CY_TCH_MAJ] = tmp / si->sensing_conf_data.len_x; + tmp = tch->abs[CY_TCH_MIN] * 100 * si->sensing_conf_data.res_x; + tch->abs[CY_TCH_MIN] = tmp / si->sensing_conf_data.len_x; + + t = tch->abs[CY_TCH_T]; + input_mt_slot(ts->input, t); + input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); + __set_bit(t, ids); + + /* position and pressure fields */ + touchscreen_report_pos(ts->input, &ts->prop, + tch->abs[CY_TCH_X], tch->abs[CY_TCH_Y], + true); + input_report_abs(ts->input, ABS_MT_PRESSURE, + tch->abs[CY_TCH_P]); + + /* Get the extended touch fields */ + input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, + tch->abs[CY_TCH_MAJ]); + input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, + tch->abs[CY_TCH_MIN]); + } + + ts->num_prv_rec = num_cur_tch; +} + +static int cyttsp5_mt_attention(struct device *dev) +{ + struct cyttsp5 *ts = dev_get_drvdata(dev); + struct cyttsp5_sysinfo *si = &ts->sysinfo; + int max_tch = si->sensing_conf_data.max_tch; + struct cyttsp5_touch tch; + u8 num_cur_tch; + + cyttsp5_get_touch_axis((int *) &num_cur_tch, si->tch_hdr.size, + si->tch_hdr.max, + ts->input_buf + 3 + si->tch_hdr.ofs, + si->tch_hdr.bofs); + + if (num_cur_tch > max_tch) { + dev_err(dev, "Num touch err detected (n=%d)\n", num_cur_tch); + num_cur_tch = max_tch; + } + + if (num_cur_tch == 0 && ts->num_prv_rec == 0) + return 0; + + /* extract xy_data for all currently reported touches */ + if (num_cur_tch) + cyttsp5_get_mt_touches(ts, &tch, num_cur_tch); + + input_mt_sync_frame(ts->input); + input_sync(ts->input); + + return 0; +} + +static int cyttsp5_setup_input_device(struct device *dev) +{ + struct cyttsp5 *ts = dev_get_drvdata(dev); + struct cyttsp5_sysinfo *si = &ts->sysinfo; + int max_x, max_y, max_p; + int max_x_tmp, max_y_tmp; + int error; + + max_x_tmp = si->sensing_conf_data.res_x; + max_y_tmp = si->sensing_conf_data.res_y; + max_x = max_x_tmp - 1; + max_y = max_y_tmp - 1; + max_p = si->sensing_conf_data.max_z; + + input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, max_x, 0, 0); + input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, max_y, 0, 0); + input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, max_p, 0, 0); + + input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, MAX_AREA, 0, 0); + input_set_abs_params(ts->input, ABS_MT_TOUCH_MINOR, 0, MAX_AREA, 0, 0); + + error = input_mt_init_slots(ts->input, si->tch_abs[CY_TCH_T].max, + INPUT_MT_DROP_UNUSED | INPUT_MT_DIRECT); + if (error < 0) + return error; + + error = input_register_device(ts->input); + if (error < 0) + dev_err(dev, "Error, failed register input device r=%d\n", error); + + return error; +} + +static int cyttsp5_parse_dt_key_code(struct device *dev) +{ + struct cyttsp5 *ts = dev_get_drvdata(dev); + struct cyttsp5_sysinfo *si = &ts->sysinfo; + int i; + + if (!si->num_btns) + return 0; + + /* Initialize the button to RESERVED */ + for (i = 0; i < si->num_btns; i++) + si->key_code[i] = KEY_RESERVED; + + return device_property_read_u32_array(dev, "linux,keycodes", + si->key_code, si->num_btns); +} + +static int cyttsp5_btn_attention(struct device *dev) +{ + struct cyttsp5 *ts = dev_get_drvdata(dev); + struct cyttsp5_sysinfo *si = &ts->sysinfo; + int cur_btn, offset = 0; + int cur_btn_state; + + switch (ts->input_buf[2]) { + case HID_TOUCH_REPORT_ID: + offset = TOUCH_INPUT_HEADER_SIZE; + break; + case HID_BTN_REPORT_ID: + offset = BTN_INPUT_HEADER_SIZE; + break; + } + + if (ts->input_buf[2] != HID_BTN_REPORT_ID || !si->num_btns) + return 0; + + /* extract button press/release touch information */ + for (cur_btn = 0; cur_btn < si->num_btns; cur_btn++) { + /* Get current button state */ + cur_btn_state = (ts->input_buf[offset] >> (cur_btn * CY_BITS_PER_BTN)) + & CY_NUM_BTN_EVENT_ID; + + input_report_key(ts->input, si->key_code[cur_btn], + cur_btn_state); + input_sync(ts->input); + } + + return 0; +} + +static int cyttsp5_validate_cmd_response(struct cyttsp5 *ts, u8 code) +{ + u16 size, crc; + u8 status, report_id; + int command_code; + + size = get_unaligned_le16(&ts->response_buf[0]); + + if (!size) + return 0; + + report_id = ts->response_buf[HID_OUTPUT_RESPONSE_REPORT_OFFSET]; + + switch (report_id) { + case HID_BL_RESPONSE_REPORT_ID: { + if (ts->response_buf[4] != HID_OUTPUT_BL_SOP) { + dev_err(ts->dev, "HID output response, wrong SOP\n"); + return -EPROTO; + } + + if (ts->response_buf[size - 1] != HID_OUTPUT_BL_EOP) { + dev_err(ts->dev, "HID output response, wrong EOP\n"); + return -EPROTO; + } + + crc = crc_itu_t(0xFFFF, &ts->response_buf[4], size - 7); + if (ts->response_buf[size - 3] != LOW_BYTE(crc) || + ts->response_buf[size - 2] != HI_BYTE(crc)) { + dev_err(ts->dev, "HID output response, wrong CRC 0x%X\n", + crc); + return -EPROTO; + } + + status = ts->response_buf[5]; + if (status) { + dev_err(ts->dev, "HID output response, ERROR:%d\n", + status); + return -EPROTO; + } + break; + } + case HID_APP_RESPONSE_REPORT_ID: { + command_code = ts->response_buf[HID_OUTPUT_RESPONSE_CMD_OFFSET] + & HID_OUTPUT_RESPONSE_CMD_MASK; + if (command_code != code) { + dev_err(ts->dev, + "HID output response, wrong command_code:%X\n", + command_code); + return -EPROTO; + } + break; + } + } + + return 0; +} + +static void cyttsp5_si_get_btn_data(struct cyttsp5 *ts) +{ + struct cyttsp5_sysinfo *si = &ts->sysinfo; + unsigned int btns = ts->response_buf[HID_SYSINFO_BTN_OFFSET] + & HID_SYSINFO_BTN_MASK; + + si->num_btns = hweight8(btns); +} + +static int cyttsp5_get_sysinfo_regs(struct cyttsp5 *ts) +{ + struct cyttsp5_sensing_conf_data *scd = &ts->sysinfo.sensing_conf_data; + struct cyttsp5_sensing_conf_data_dev *scd_dev = + (struct cyttsp5_sensing_conf_data_dev *) + &ts->response_buf[HID_SYSINFO_SENSING_OFFSET]; + + cyttsp5_si_get_btn_data(ts); + + scd->max_tch = scd_dev->max_num_of_tch_per_refresh_cycle; + scd->res_x = get_unaligned_le16(&scd_dev->res_x); + scd->res_y = get_unaligned_le16(&scd_dev->res_y); + scd->max_z = get_unaligned_le16(&scd_dev->max_z); + scd->len_x = get_unaligned_le16(&scd_dev->len_x); + scd->len_y = get_unaligned_le16(&scd_dev->len_y); + + return 0; +} + +static int cyttsp5_hid_output_get_sysinfo(struct cyttsp5 *ts) +{ + int rc; + u8 cmd[HID_OUTPUT_GET_SYSINFO_SIZE]; + + /* HI bytes of Output register address */ + cmd[0] = LOW_BYTE(HID_OUTPUT_GET_SYSINFO_SIZE); + cmd[1] = HI_BYTE(HID_OUTPUT_GET_SYSINFO_SIZE); + cmd[2] = HID_APP_OUTPUT_REPORT_ID; + cmd[3] = 0x0; /* Reserved */ + cmd[4] = HID_OUTPUT_GET_SYSINFO; + + rc = cyttsp5_write(ts, HID_OUTPUT_REG, cmd, + HID_OUTPUT_GET_SYSINFO_SIZE); + if (rc) { + dev_err(ts->dev, "Failed to write command %d", rc); + return rc; + } + + rc = wait_for_completion_interruptible_timeout(&ts->cmd_done, + msecs_to_jiffies(CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT)); + if (rc <= 0) { + dev_err(ts->dev, "HID output cmd execution timed out\n"); + rc = -ETIME; + return rc; + } + + rc = cyttsp5_validate_cmd_response(ts, HID_OUTPUT_GET_SYSINFO); + if (rc) { + dev_err(ts->dev, "Validation of the response failed\n"); + return rc; + } + + return cyttsp5_get_sysinfo_regs(ts); +} + +static int cyttsp5_hid_output_bl_launch_app(struct cyttsp5 *ts) +{ + int rc; + u8 cmd[HID_OUTPUT_BL_LAUNCH_APP]; + u16 crc; + + cmd[0] = LOW_BYTE(HID_OUTPUT_BL_LAUNCH_APP_SIZE); + cmd[1] = HI_BYTE(HID_OUTPUT_BL_LAUNCH_APP_SIZE); + cmd[2] = HID_BL_OUTPUT_REPORT_ID; + cmd[3] = 0x0; /* Reserved */ + cmd[4] = HID_OUTPUT_BL_SOP; + cmd[5] = HID_OUTPUT_BL_LAUNCH_APP; + cmd[6] = 0x0; /* Low bytes of data */ + cmd[7] = 0x0; /* Hi bytes of data */ + crc = crc_itu_t(0xFFFF, &cmd[4], 4); + cmd[8] = LOW_BYTE(crc); + cmd[9] = HI_BYTE(crc); + cmd[10] = HID_OUTPUT_BL_EOP; + + rc = cyttsp5_write(ts, HID_OUTPUT_REG, cmd, + HID_OUTPUT_BL_LAUNCH_APP_SIZE); + if (rc) { + dev_err(ts->dev, "Failed to write command %d", rc); + return rc; + } + + rc = wait_for_completion_interruptible_timeout(&ts->cmd_done, + msecs_to_jiffies(CY_HID_OUTPUT_TIMEOUT)); + if (rc <= 0) { + dev_err(ts->dev, "HID output cmd execution timed out\n"); + rc = -ETIME; + return rc; + } + + rc = cyttsp5_validate_cmd_response(ts, HID_OUTPUT_BL_LAUNCH_APP); + if (rc) { + dev_err(ts->dev, "Validation of the response failed\n"); + return rc; + } + + return 0; +} + +static int cyttsp5_get_hid_descriptor(struct cyttsp5 *ts, + struct cyttsp5_hid_desc *desc) +{ + struct device *dev = ts->dev; + __le16 hid_desc_register = HID_DESC_REG; + int rc; + u8 cmd[2]; + + /* Set HID descriptor register */ + memcpy(cmd, &hid_desc_register, sizeof(hid_desc_register)); + + rc = cyttsp5_write(ts, HID_DESC_REG, NULL, 0); + if (rc) { + dev_err(dev, "Failed to get HID descriptor, rc=%d\n", rc); + return rc; + } + + rc = wait_for_completion_interruptible_timeout(&ts->cmd_done, + msecs_to_jiffies(CY_HID_GET_HID_DESCRIPTOR_TIMEOUT)); + if (rc <= 0) { + dev_err(ts->dev, "HID get descriptor timed out\n"); + rc = -ETIME; + return rc; + } + + memcpy(desc, ts->response_buf, sizeof(struct cyttsp5_hid_desc)); + + /* Check HID descriptor length and version */ + if (le16_to_cpu(desc->hid_desc_len) != sizeof(*desc) || + le16_to_cpu(desc->bcd_version) != HID_VERSION) { + dev_err(dev, "Unsupported HID version\n"); + return -ENODEV; + } + + return 0; +} + +static int fill_tch_abs(struct cyttsp5_tch_abs_params *tch_abs, int report_size, + int offset) +{ + tch_abs->ofs = offset / 8; + tch_abs->size = report_size / 8; + if (report_size % 8) + tch_abs->size += 1; + tch_abs->min = 0; + tch_abs->max = 1 << report_size; + tch_abs->bofs = offset - (tch_abs->ofs << 3); + + return 0; +} + +static irqreturn_t cyttsp5_handle_irq(int irq, void *handle) +{ + struct cyttsp5 *ts = handle; + int report_id; + int size; + int error; + + error = cyttsp5_read(ts, ts->input_buf, CY_MAX_INPUT); + if (error) + return IRQ_HANDLED; + + size = get_unaligned_le16(&ts->input_buf[0]); + + if (size == 0) { + /* reset */ + report_id = 0; + size = 2; + } else { + report_id = ts->input_buf[2]; + } + + switch (report_id) { + case HID_TOUCH_REPORT_ID: + cyttsp5_mt_attention(ts->dev); + break; + case HID_BTN_REPORT_ID: + cyttsp5_btn_attention(ts->dev); + break; + default: + /* It is not an input but a command response */ + memcpy(ts->response_buf, ts->input_buf, size); + complete(&ts->cmd_done); + } + + return IRQ_HANDLED; +} + +static int cyttsp5_deassert_int(struct cyttsp5 *ts) +{ + u16 size; + u8 buf[2]; + int error; + + error = regmap_bulk_read(ts->regmap, HID_INPUT_REG, buf, 2); + if (error < 0) + return error; + + size = get_unaligned_le16(&buf[0]); + if (size == 2 || size == 0) + return 0; + + return -EINVAL; +} + +static int cyttsp5_fill_all_touch(struct cyttsp5 *ts) +{ + struct cyttsp5_sysinfo *si = &ts->sysinfo; + + fill_tch_abs(&si->tch_abs[CY_TCH_X], REPORT_SIZE_16, + TOUCH_REPORT_DESC_X); + fill_tch_abs(&si->tch_abs[CY_TCH_Y], REPORT_SIZE_16, + TOUCH_REPORT_DESC_Y); + fill_tch_abs(&si->tch_abs[CY_TCH_P], REPORT_SIZE_8, + TOUCH_REPORT_DESC_P); + fill_tch_abs(&si->tch_abs[CY_TCH_T], REPORT_SIZE_5, + TOUCH_REPORT_DESC_CONTACTID); + fill_tch_abs(&si->tch_hdr, REPORT_SIZE_5, + TOUCH_REPORT_DESC_HDR_CONTACTCOUNT); + fill_tch_abs(&si->tch_abs[CY_TCH_MAJ], REPORT_SIZE_8, + TOUCH_REPORT_DESC_MAJ); + fill_tch_abs(&si->tch_abs[CY_TCH_MIN], REPORT_SIZE_8, + TOUCH_REPORT_DESC_MIN); + + return 0; +} + +static int cyttsp5_startup(struct cyttsp5 *ts) +{ + int error; + + error = cyttsp5_deassert_int(ts); + if (error) { + dev_err(ts->dev, "Error on deassert int r=%d\n", error); + return -ENODEV; + } + + /* + * Launch the application as the device starts in bootloader mode + * because of a power-on-reset + */ + error = cyttsp5_hid_output_bl_launch_app(ts); + if (error < 0) { + dev_err(ts->dev, "Error on launch app r=%d\n", error); + return error; + } + + error = cyttsp5_get_hid_descriptor(ts, &ts->hid_desc); + if (error < 0) { + dev_err(ts->dev, "Error on getting HID descriptor r=%d\n", error); + return error; + } + + error = cyttsp5_fill_all_touch(ts); + if (error < 0) { + dev_err(ts->dev, "Error on report descriptor r=%d\n", error); + return error; + } + + error = cyttsp5_hid_output_get_sysinfo(ts); + if (error) { + dev_err(ts->dev, "Error on getting sysinfo r=%d\n", error); + return error; + } + + return error; +} + +#ifdef CONFIG_OF +static const struct of_device_id cyttsp5_of_match[] = { + { .compatible = "cypress,tt21000", }, + { } +}; +MODULE_DEVICE_TABLE(of, cyttsp5_of_match); +#endif + +static const struct i2c_device_id cyttsp5_i2c_id[] = { + { CYTTSP5_NAME, 0, }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id); + +static void cyttsp5_cleanup(void *data) +{ + struct cyttsp5 *ts = data; + + regulator_disable(ts->vdd); +} + +static int cyttsp5_probe(struct device *dev, struct regmap *regmap, int irq, + const char *name) +{ + struct cyttsp5 *ts; + struct cyttsp5_sysinfo *si; + int error, i; + + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + /* Initialize device info */ + ts->regmap = regmap; + ts->dev = dev; + si = &ts->sysinfo; + dev_set_drvdata(dev, ts); + + init_completion(&ts->cmd_done); + + /* Power up the device */ + ts->vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(ts->vdd)) { + error = PTR_ERR(ts->vdd); + dev_set_drvdata(dev, NULL); + return error; + } + + error = devm_add_action_or_reset(dev, cyttsp5_cleanup, ts); + if (error) { + dev_set_drvdata(dev, NULL); + return error; + } + + error = regulator_enable(ts->vdd); + if (error) { + dev_set_drvdata(dev, NULL); + return error; + } + + ts->input = devm_input_allocate_device(dev); + if (!ts->input) { + dev_err(dev, "Error, failed to allocate input device\n"); + return -ENODEV; + } + + ts->input->name = "cyttsp5"; + scnprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); + ts->input->phys = ts->phys; + input_set_drvdata(ts->input, ts); + + /* Reset the gpio to be in a reset state */ + ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ts->reset_gpio)) { + error = PTR_ERR(ts->reset_gpio); + dev_err(dev, "Failed to request reset gpio, error %d\n", error); + return error; + } + gpiod_set_value(ts->reset_gpio, 0); + + /* Need a delay to have device up */ + msleep(20); + + error = devm_request_threaded_irq(dev, irq, NULL, cyttsp5_handle_irq, + IRQF_ONESHOT, name, ts); + if (error) { + dev_err(dev, "unable to request IRQ\n"); + return error; + } + + error = cyttsp5_startup(ts); + if (error) { + dev_err(ts->dev, "Fail initial startup r=%d\n", error); + return error; + } + + error = cyttsp5_parse_dt_key_code(dev); + if (error < 0) { + dev_err(ts->dev, "Error while parsing dts %d\n", error); + return error; + } + + touchscreen_parse_properties(ts->input, true, &ts->prop); + + __set_bit(EV_KEY, ts->input->evbit); + for (i = 0; i < si->num_btns; i++) + __set_bit(si->key_code[i], ts->input->keybit); + + return cyttsp5_setup_input_device(dev); +} + +static int cyttsp5_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + static const struct regmap_config config = { + .reg_bits = 8, + .val_bits = 8, + }; + + regmap = devm_regmap_init_i2c(client, &config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "regmap allocation failed: %ld\n", + PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return cyttsp5_probe(&client->dev, regmap, client->irq, client->name); +} + +static struct i2c_driver cyttsp5_i2c_driver = { + .driver = { + .name = CYTTSP5_NAME, + .of_match_table = of_match_ptr(cyttsp5_of_match), + }, + .probe = cyttsp5_i2c_probe, + .id_table = cyttsp5_i2c_id, +}; + +module_i2c_driver(cyttsp5_i2c_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Touchscreen driver for Cypress TrueTouch Gen 5 Product"); +MODULE_AUTHOR("Mylène Josserand "); -- 2.31.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C9313C433EF for ; Wed, 22 Dec 2021 12:47:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=X44WCAM6Rfj8Q5yz4I5jVhaOVmPzzi6wC+FO3Shfb7A=; b=2eiFiNhBYxK5ak iHap12wFMGNyR02rPXWZ+vOdNaTUcWysfGsNpQFSWLgB0JbjV2JVfLX5RPleXhgH8bXh9jRRycHMt px8FpP10nrAgfRsFg4zFYELiOvieDAK4ge4JD7z7KIvzU2hYdSjJ5QFhIC51r5amByIh/Jk36cKYH VAWYyyfIGz+5dkhuwDT5KyCspjeeGWR8WsoGtL7N8q7lN5O2c8p2uFsaumyghMFoO0eRRzJyNI904 28uUhCW+dl+5z3BDfziaypreCLJvHJAJ/ulUIeNFo94iymgMy8vSjx5cMWGARDBB7l4F2x8wshXC9 WNahdn8q0aK7P+vHXyHA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1n010p-00AJdd-R8; Wed, 22 Dec 2021 12:46:32 +0000 Received: from new3-smtp.messagingengine.com ([66.111.4.229]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1n010b-00AJZE-BP for linux-arm-kernel@lists.infradead.org; Wed, 22 Dec 2021 12:46:20 +0000 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailnew.nyi.internal (Postfix) with ESMTP id AFFFD5803DA; Wed, 22 Dec 2021 07:46:16 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Wed, 22 Dec 2021 07:46:16 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alistair23.me; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; s=fm2; bh= BlYqeqemM2kH0tviP1iG5/7ttzsJ4yS4sPMdY5h7Gxc=; b=gPLylzwMNCOv2hLF C4PgfPtHBpopxACSozmIoatyAqcw/ClSw9RxOG4NCt4wIrT011rzGkQGqlU9HIBs wCM/M+xWS1wL6XO4p2b5FQGwEwmfzpztx/wCSW5IF1vff8zA553RmuJEJQy+oHq5 gW8lMxFdf4XmgBxOcEuJ0lizOmw58Dj5PW7KeODBdK4yjUDkLsqPhP+raHF9cqNF 2Ftdb8uEjliUPvsPoOVMtipyW8MFWzmB/N7zqOllG7DgQgQrpcyiLcWOaKrMF3mS 3RG0R9Jb6JsWD8Hh5873p5/M01jCS9eraP4/gx9n5axMP+O3p6QPXHgccOL0vQdu LafwxA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm1; bh=BlYqeqemM2kH0tviP1iG5/7ttzsJ4yS4sPMdY5h7G xc=; b=jnScgZ4GHW7ZN6E88WCUh0VyEm4BSnCMCzorFBGGgVJwXawGG1pCcen/0 oZ2ceTNe86NOZW7ObFMDud8ZTnGm3z3vQZvkqMwDHURiZT4ncN7de2Aqv6mma8vt xzNLVYOfbIF7KuHAQHYfkO2SpbQ18FUtpFPHOCs1CN8egPCiGrw5hHNsmxIPDJSi Na8xjolEevlPGFKjwnuuDFsBynO/4uuRegGv2s4E8VXqwHyDSgehqkOty1QAiyCC Ne1gwJmMX/zCD29uFdFt9fkc3EYkgD9n2PtlM9HWOkdDEOFUlCTpE0jAg6QNQ/4E FgW0YALfYRKNpf9rMSiGRVF7GpaIg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvuddruddtiedgfeejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfgggtgfesthekredtredtjeenucfhrhhomheptehlihhs thgrihhrucfhrhgrnhgtihhsuceorghlihhsthgrihhrsegrlhhishhtrghirhdvfedrmh gvqeenucggtffrrghtthgvrhhnpeejfeethfefudefgeffkefgueffgeefteefgfffheeg lefgvddvheevtdeuueejjeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmh grihhlfhhrohhmpegrlhhishhtrghirhesrghlihhsthgrihhrvdefrdhmvg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 22 Dec 2021 07:46:12 -0500 (EST) From: Alistair Francis To: devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org Cc: dmitry.torokhov@gmail.com, alistair23@gmail.com, robh+dt@kernel.org, linus.walleij@linaro.org, rydberg@bitmath.org, andreas@kemnade.info, =?UTF-8?q?Myl=C3=A8ne=20Josserand?= , Maxime Ripard , Alistair Francis Subject: [PATCH v4 1/4] Input: Add driver for Cypress Generation 5 touchscreen Date: Wed, 22 Dec 2021 22:46:00 +1000 Message-Id: <20211222124603.326920-2-alistair@alistair23.me> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211222124603.326920-1-alistair@alistair23.me> References: <20211222124603.326920-1-alistair@alistair23.me> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211222_044617_608163_807543C8 X-CRM114-Status: GOOD ( 27.67 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org RnJvbTogTXlsw6huZSBKb3NzZXJhbmQgPG15bGVuZS5qb3NzZXJhbmRAYm9vdGxpbi5jb20+CgpU aGlzIGlzIHRoZSBiYXNpYyBkcml2ZXIgZm9yIHRoZSBDeXByZXNzIFRydWVUb3VjaCBHZW41IHRv dWNoc2NyZWVuCmNvbnRyb2xsZXJzLiBUaGlzIGRyaXZlciBzdXBwb3J0cyBvbmx5IHRoZSBJMkMg YnVzIGJ1dCBpdCB1c2VzIHJlZ21hcApzbyBTUEkgc3VwcG9ydCBjb3VsZCBiZSBhZGRlZCBsYXRl ci4KVGhlIHRvdWNoc2NyZWVuIGNhbiByZXRyaWV2ZSBzb21lIGRlZmluZWQgem9uZSB0aGF0IGFy ZSBoYW5kbGVkIGFzCmJ1dHRvbnMgKGFjY29yZGluZyB0byB0aGUgaGFyZHdhcmUpLiBUaGF0IGlz IHdoeSBpdCBoYW5kbGVzCmJ1dHRvbiBhbmQgbXVsdGl0b3VjaCBldmVudHMuCgpSZXZpZXdlZC1i eTogTWF4aW1lIFJpcGFyZCA8bWF4aW1lLnJpcGFyZEBib290bGluLmNvbT4KU2lnbmVkLW9mZi1i eTogTXlsw6huZSBKb3NzZXJhbmQgPG15bGVuZS5qb3NzZXJhbmRAYm9vdGxpbi5jb20+ClNpZ25l ZC1vZmYtYnk6IEFsaXN0YWlyIEZyYW5jaXMgPGFsaXN0YWlyQGFsaXN0YWlyMjMubWU+Ci0tLQog ZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9LY29uZmlnICAgfCAgMTQgKwogZHJpdmVycy9pbnB1 dC90b3VjaHNjcmVlbi9NYWtlZmlsZSAgfCAgIDEgKwogZHJpdmVycy9pbnB1dC90b3VjaHNjcmVl bi9jeXR0c3A1LmMgfCA5MjIgKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogMyBmaWxlcyBj aGFuZ2VkLCA5MzcgaW5zZXJ0aW9ucygrKQogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaW5w dXQvdG91Y2hzY3JlZW4vY3l0dHNwNS5jCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9pbnB1dC90b3Vj aHNjcmVlbi9LY29uZmlnIGIvZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9LY29uZmlnCmluZGV4 IDJmNmFkZmI3YjkzOC4uNjFmMDQ1MjA1MGY2IDEwMDY0NAotLS0gYS9kcml2ZXJzL2lucHV0L3Rv dWNoc2NyZWVuL0tjb25maWcKKysrIGIvZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9LY29uZmln CkBAIC0yODQsNiArMjg0LDIwIEBAIGNvbmZpZyBUT1VDSFNDUkVFTl9DWVRUU1A0X1NQSQogCSAg VG8gY29tcGlsZSB0aGlzIGRyaXZlciBhcyBhIG1vZHVsZSwgY2hvb3NlIE0gaGVyZTogdGhlCiAJ ICBtb2R1bGUgd2lsbCBiZSBjYWxsZWQgY3l0dHNwNF9zcGkuCiAKK2NvbmZpZyBUT1VDSFNDUkVF Tl9DWVRUU1A1CisJdHJpc3RhdGUgIkN5cHJlc3MgVHJ1ZVRvdWNoIEdlbjUgVG91Y2hzY3JlZW4g RHJpdmVyIgorCWRlcGVuZHMgb24gT0YgJiYgSTJDCisJc2VsZWN0IFJFR01BUF9JMkMKKwlzZWxl Y3QgQ1JDX0lUVV9UCisJaGVscAorCSAgRHJpdmVyIGZvciBQYXJhZGUgVHJ1ZVRvdWNoIFN0YW5k YXJkIFByb2R1Y3QKKwkgIEdlbmVyYXRpb24gNSB0b3VjaHNjcmVlbiBjb250cm9sbGVycy4KKwkg IEkyQyBidXMgaW50ZXJmYWNlIHN1cHBvcnQgb25seS4KKwkgIFNheSBZIGhlcmUgaWYgeW91IGhh dmUgYSBDeXByZXNzIEdlbjUgdG91Y2hzY3JlZW4uCisJICBJZiB1bnN1cmUsIHNheSBOLgorCSAg VG8gY29tcGlsZSB0aGlzIGRyaXZlciBhcyBhIG1vZHVsZSwgY2hvb3NlIE0gaGVyZTogdGhlCisJ ICBtb2R1bGUgd2lsbCBiZSBjYWxsZWQgY3l0dHNwNS4KKwogY29uZmlnIFRPVUNIU0NSRUVOX0RB OTAzNAogCXRyaXN0YXRlICJUb3VjaHNjcmVlbiBzdXBwb3J0IGZvciBEaWFsb2cgU2VtaWNvbmR1 Y3RvciBEQTkwMzQiCiAJZGVwZW5kcyBvbiBQTUlDX0RBOTAzWApkaWZmIC0tZ2l0IGEvZHJpdmVy cy9pbnB1dC90b3VjaHNjcmVlbi9NYWtlZmlsZSBiL2RyaXZlcnMvaW5wdXQvdG91Y2hzY3JlZW4v TWFrZWZpbGUKaW5kZXggMzlhODEyN2NmNmE1Li4wZWE1YzQ3ZjdmZDkgMTAwNjQ0Ci0tLSBhL2Ry aXZlcnMvaW5wdXQvdG91Y2hzY3JlZW4vTWFrZWZpbGUKKysrIGIvZHJpdmVycy9pbnB1dC90b3Vj aHNjcmVlbi9NYWtlZmlsZQpAQCAtMzAsNiArMzAsNyBAQCBvYmotJChDT05GSUdfVE9VQ0hTQ1JF RU5fQ1lUVFNQX1NQSSkJKz0gY3l0dHNwX3NwaS5vCiBvYmotJChDT05GSUdfVE9VQ0hTQ1JFRU5f Q1lUVFNQNF9DT1JFKQkrPSBjeXR0c3A0X2NvcmUubwogb2JqLSQoQ09ORklHX1RPVUNIU0NSRUVO X0NZVFRTUDRfSTJDKQkrPSBjeXR0c3A0X2kyYy5vIGN5dHRzcF9pMmNfY29tbW9uLm8KIG9iai0k KENPTkZJR19UT1VDSFNDUkVFTl9DWVRUU1A0X1NQSSkJKz0gY3l0dHNwNF9zcGkubworb2JqLSQo Q09ORklHX1RPVUNIU0NSRUVOX0NZVFRTUDUpCSs9IGN5dHRzcDUubwogb2JqLSQoQ09ORklHX1RP VUNIU0NSRUVOX0RBOTAzNCkJKz0gZGE5MDM0LXRzLm8KIG9iai0kKENPTkZJR19UT1VDSFNDUkVF Tl9EQTkwNTIpCSs9IGRhOTA1Ml90c2kubwogb2JqLSQoQ09ORklHX1RPVUNIU0NSRUVOX0RZTkFQ Uk8pCSs9IGR5bmFwcm8ubwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9j eXR0c3A1LmMgYi9kcml2ZXJzL2lucHV0L3RvdWNoc2NyZWVuL2N5dHRzcDUuYwpuZXcgZmlsZSBt b2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLmYwZDFmYTI3ZTE3ZQotLS0gL2Rldi9udWxs CisrKyBiL2RyaXZlcnMvaW5wdXQvdG91Y2hzY3JlZW4vY3l0dHNwNS5jCkBAIC0wLDAgKzEsOTIy IEBACisvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAorLyoKKyAqIFBhcmFkZSBU cnVlVG91Y2goVE0pIFN0YW5kYXJkIFByb2R1Y3QgVjUgTW9kdWxlLgorICoKKyAqIENvcHlyaWdo dCAoQykgMjAxNSBQYXJhZGUgVGVjaG5vbG9naWVzCisgKiBDb3B5cmlnaHQgKEMpIDIwMTItMjAx NSBDeXByZXNzIFNlbWljb25kdWN0b3IKKyAqIENvcHlyaWdodCAoQykgMjAxOCBCb290bGluCisg KgorICogQXV0aG9yczogTXlsw6huZSBKb3NzZXJhbmQgPG15bGVuZS5qb3NzZXJhbmRAYm9vdGxp bi5jb20+CisgKiAgICAgICAgICAgICAgICBBbGlzdGFpciBGcmFuY2lzIDxhbGlzdGFpckBhbGlz dGFpcjIzLm1lPgorICoKKyAqLworCisjaW5jbHVkZSA8YXNtL3VuYWxpZ25lZC5oPgorI2luY2x1 ZGUgPGxpbnV4L2NyYy1pdHUtdC5oPgorI2luY2x1ZGUgPGxpbnV4L2RlbGF5Lmg+CisjaW5jbHVk ZSA8bGludXgvZGV2aWNlLmg+CisjaW5jbHVkZSA8bGludXgvZ3Bpby5oPgorI2luY2x1ZGUgPGxp bnV4L2dwaW8vY29uc3VtZXIuaD4KKyNpbmNsdWRlIDxsaW51eC9pbnB1dC9tdC5oPgorI2luY2x1 ZGUgPGxpbnV4L2lucHV0L3RvdWNoc2NyZWVuLmg+CisjaW5jbHVkZSA8bGludXgvaW50ZXJydXB0 Lmg+CisjaW5jbHVkZSA8bGludXgvaTJjLmg+CisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+Cisj aW5jbHVkZSA8bGludXgvb2ZfZGV2aWNlLmg+CisjaW5jbHVkZSA8bGludXgvcmVnbWFwLmg+CisK KyNkZWZpbmUgQ1lUVFNQNV9OQU1FCQkJCSJjeXR0c3A1IgorI2RlZmluZSBDWV9JMkNfREFUQV9T SVpFCQkJKDIgKiAyNTYpCisjZGVmaW5lIEhJRF9WRVJTSU9OCQkJCTB4MDEwMAorI2RlZmluZSBD WV9NQVhfSU5QVVQJCQkJNTEyCisjZGVmaW5lIENZVFRTUDVfUFJFQUxMT0NBVEVEX0NNRF9CVUZG RVIJMzIKKyNkZWZpbmUgQ1lfQklUU19QRVJfQlROCQkJMQorI2RlZmluZSBDWV9OVU1fQlROX0VW RU5UX0lECQkJKCgxIDw8IENZX0JJVFNfUEVSX0JUTikgLSAxKQorCisjZGVmaW5lIE1BWF9BUkVB CQkJCTI1NQorI2RlZmluZSBISURfT1VUUFVUX0JMX1NPUAkJCTB4MQorI2RlZmluZSBISURfT1VU UFVUX0JMX0VPUAkJCTB4MTcKKyNkZWZpbmUgSElEX09VVFBVVF9CTF9MQVVOQ0hfQVBQCQkweDNC CisjZGVmaW5lIEhJRF9PVVRQVVRfQkxfTEFVTkNIX0FQUF9TSVpFCQkxMQorI2RlZmluZSBISURf T1VUUFVUX0dFVF9TWVNJTkZPCQkJMHgyCisjZGVmaW5lIEhJRF9PVVRQVVRfR0VUX1NZU0lORk9f U0laRQkJNQorI2RlZmluZSBISURfT1VUUFVUX01BWF9DTURfU0laRQkJMTIKKworI2RlZmluZSBI SURfREVTQ19SRUcJCQkJMHgxCisjZGVmaW5lIEhJRF9JTlBVVF9SRUcJCQkJMHgzCisjZGVmaW5l IEhJRF9PVVRQVVRfUkVHCQkJCTB4NAorCisjZGVmaW5lIFJFUE9SVF9JRF9UT1VDSAkJCTB4MQor I2RlZmluZSBSRVBPUlRfSURfQlROCQkJCTB4MworI2RlZmluZSBSRVBPUlRfU0laRV81CQkJCTUK KyNkZWZpbmUgUkVQT1JUX1NJWkVfOAkJCQk4CisjZGVmaW5lIFJFUE9SVF9TSVpFXzE2CQkJCTE2 CisKKy8qIFRvdWNoIHJlcG9ydHMgb2Zmc2V0cyAqLworLyogSGVhZGVyIG9mZnNldHMgKi8KKyNk ZWZpbmUgVE9VQ0hfUkVQT1JUX0RFU0NfSERSX0NPTlRBQ1RDT1VOVAkxNgorLyogUmVjb3JkIG9m ZnNldHMgKi8KKyNkZWZpbmUgVE9VQ0hfUkVQT1JUX0RFU0NfQ09OVEFDVElECQk4CisjZGVmaW5l IFRPVUNIX1JFUE9SVF9ERVNDX1gJCQkxNgorI2RlZmluZSBUT1VDSF9SRVBPUlRfREVTQ19ZCQkJ MzIKKyNkZWZpbmUgVE9VQ0hfUkVQT1JUX0RFU0NfUAkJCTQ4CisjZGVmaW5lIFRPVUNIX1JFUE9S VF9ERVNDX01BSgkJCTU2CisjZGVmaW5lIFRPVUNIX1JFUE9SVF9ERVNDX01JTgkJCTY0CisKKy8q IEhJRCAqLworI2RlZmluZSBISURfVE9VQ0hfUkVQT1JUX0lECQkJMHgxCisjZGVmaW5lIEhJRF9C VE5fUkVQT1JUX0lECQkJMHgzCisjZGVmaW5lIEhJRF9BUFBfUkVTUE9OU0VfUkVQT1JUX0lECQkw eDFGCisjZGVmaW5lIEhJRF9BUFBfT1VUUFVUX1JFUE9SVF9JRAkJMHgyRgorI2RlZmluZSBISURf QkxfUkVTUE9OU0VfUkVQT1JUX0lECQkweDMwCisjZGVmaW5lIEhJRF9CTF9PVVRQVVRfUkVQT1JU X0lECQkweDQwCisKKyNkZWZpbmUgSElEX09VVFBVVF9SRVNQT05TRV9SRVBPUlRfT0ZGU0VUCTIK KyNkZWZpbmUgSElEX09VVFBVVF9SRVNQT05TRV9DTURfT0ZGU0VUCQk0CisjZGVmaW5lIEhJRF9P VVRQVVRfUkVTUE9OU0VfQ01EX01BU0sJCTB4N0YKKworI2RlZmluZSBISURfU1lTSU5GT19TRU5T SU5HX09GRlNFVAkJMzMKKyNkZWZpbmUgSElEX1NZU0lORk9fQlROX09GRlNFVAkJCTQ4CisjZGVm aW5lIEhJRF9TWVNJTkZPX0JUTl9NQVNLCQkJMHhGRgorI2RlZmluZSBISURfU1lTSU5GT19NQVhf QlROCQkJOAorCisvKiAgVGltZW91dCBpbiBtcyAqLworI2RlZmluZSBDWV9ISURfT1VUUFVUX1RJ TUVPVVQJCQkyMDAKKyNkZWZpbmUgQ1lfSElEX09VVFBVVF9HRVRfU1lTSU5GT19USU1FT1VUCTMw MDAKKyNkZWZpbmUgQ1lfSElEX0dFVF9ISURfREVTQ1JJUFRPUl9USU1FT1VUCTQwMDAKKworLyog bWF4aW11bSBudW1iZXIgb2YgY29uY3VycmVudCB0cmFja3MgKi8KKyNkZWZpbmUgVE9VQ0hfUkVQ T1JUX1NJWkUJCQkxMAorI2RlZmluZSBUT1VDSF9JTlBVVF9IRUFERVJfU0laRQkJNworI2RlZmlu ZSBCVE5fUkVQT1JUX1NJWkUJCQk5CisjZGVmaW5lIEJUTl9JTlBVVF9IRUFERVJfU0laRQkJCTUK KworI2RlZmluZSBNQVhfQ1lfVENIX1RfSURTCTMyCisKKy8qIEFsbCB1c2FnZSBwYWdlcyBmb3Ig VG91Y2ggUmVwb3J0ICovCisjZGVmaW5lIFRPVUNIX1JFUE9SVF9VU0FHRV9QR19YCQkweDAwMDEw MDMwCisjZGVmaW5lIFRPVUNIX1JFUE9SVF9VU0FHRV9QR19ZCQkweDAwMDEwMDMxCisjZGVmaW5l IFRPVUNIX1JFUE9SVF9VU0FHRV9QR19QCQkweDAwMEQwMDMwCisjZGVmaW5lIFRPVUNIX1JFUE9S VF9VU0FHRV9QR19DT05UQUNUSUQJMHgwMDBEMDA1MQorI2RlZmluZSBUT1VDSF9SRVBPUlRfVVNB R0VfUEdfQ09OVEFDVENPVU5UCTB4MDAwRDAwNTQKKyNkZWZpbmUgVE9VQ0hfUkVQT1JUX1VTQUdF X1BHX01BSgkJMHhGRjAxMDA2MgorI2RlZmluZSBUT1VDSF9SRVBPUlRfVVNBR0VfUEdfTUlOCQkw eEZGMDEwMDYzCisjZGVmaW5lIFRPVUNIX0NPTF9VU0FHRV9QRwkJCTB4MDAwRDAwMjIKKworLyog aGVscGVycyAqLworI2RlZmluZSBISV9CWVRFKHgpCQkJCSgodTgpKCgoeCkgPj4gOCkgJiAweEZG KSkKKyNkZWZpbmUgTE9XX0JZVEUoeCkJCQkJKCh1OCkoKHgpICYgMHhGRikpCisKKy8qIFN5c3Rl bSBJbmZvcm1hdGlvbiBpbnRlcmZhY2UgZGVmaW5pdGlvbnMgKi8KK3N0cnVjdCBjeXR0c3A1X3Nl bnNpbmdfY29uZl9kYXRhX2RldiB7CisJdTggZWxlY3Ryb2Rlc194OworCXU4IGVsZWN0cm9kZXNf eTsKKwlfX2xlMTYgbGVuX3g7CisJX19sZTE2IGxlbl95OworCV9fbGUxNiByZXNfeDsKKwlfX2xl MTYgcmVzX3k7CisJX19sZTE2IG1heF96OworCXU4IG9yaWdpbl94OworCXU4IG9yaWdpbl95Owor CXU4IGJ0bjsKKwl1OCBzY2FuX21vZGU7CisJdTggbWF4X251bV9vZl90Y2hfcGVyX3JlZnJlc2hf Y3ljbGU7Cit9IF9fcGFja2VkOworCitzdHJ1Y3QgY3l0dHNwNV9zZW5zaW5nX2NvbmZfZGF0YSB7 CisJdTE2IHJlc194OworCXUxNiByZXNfeTsKKwl1MTYgbWF4X3o7CisJdTE2IGxlbl94OworCXUx NiBsZW5feTsKKwl1OCBvcmlnaW5feDsKKwl1OCBvcmlnaW5feTsKKwl1OCBtYXhfdGNoOworfTsK KworZW51bSBjeXR0c3A1X3RjaF9hYnMgewkvKiBmb3Igb3JkZXJpbmcgd2l0aGluIHRoZSBleHRy YWN0ZWQgdG91Y2ggZGF0YSBhcnJheSAqLworCUNZX1RDSF9YLAkvKiBYICovCisJQ1lfVENIX1ks CS8qIFkgKi8KKwlDWV9UQ0hfUCwJLyogUCAoWikgKi8KKwlDWV9UQ0hfVCwJLyogVE9VQ0ggSUQg Ki8KKwlDWV9UQ0hfTUFKLAkvKiBUT1VDSF9NQUpPUiAqLworCUNZX1RDSF9NSU4sCS8qIFRPVUNI X01JTk9SICovCisJQ1lfVENIX05VTV9BQlMsCit9OworCitzdHJ1Y3QgY3l0dHNwNV90Y2hfYWJz X3BhcmFtcyB7CisJc2l6ZV90IG9mczsJLyogYWJzIGJ5dGUgb2Zmc2V0ICovCisJc2l6ZV90IHNp emU7CS8qIHNpemUgaW4gYml0cyAqLworCXNpemVfdCBtaW47CS8qIG1pbiB2YWx1ZSAqLworCXNp emVfdCBtYXg7CS8qIG1heCB2YWx1ZSAqLworCXNpemVfdCBib2ZzOwkvKiBiaXQgb2Zmc2V0ICov Cit9OworCitzdHJ1Y3QgY3l0dHNwNV90b3VjaCB7CisJaW50IGFic1tDWV9UQ0hfTlVNX0FCU107 Cit9OworCitzdHJ1Y3QgY3l0dHNwNV9zeXNpbmZvIHsKKwlzdHJ1Y3QgY3l0dHNwNV9zZW5zaW5n X2NvbmZfZGF0YSBzZW5zaW5nX2NvbmZfZGF0YTsKKwlpbnQgbnVtX2J0bnM7CisJc3RydWN0IGN5 dHRzcDVfdGNoX2Fic19wYXJhbXMgdGNoX2hkcjsKKwlzdHJ1Y3QgY3l0dHNwNV90Y2hfYWJzX3Bh cmFtcyB0Y2hfYWJzW0NZX1RDSF9OVU1fQUJTXTsKKwl1MzIga2V5X2NvZGVbSElEX1NZU0lORk9f TUFYX0JUTl07Cit9OworCitzdHJ1Y3QgY3l0dHNwNV9oaWRfZGVzYyB7CisJX19sZTE2IGhpZF9k ZXNjX2xlbjsKKwl1OCBwYWNrZXRfaWQ7CisJdTggcmVzZXJ2ZWRfYnl0ZTsKKwlfX2xlMTYgYmNk X3ZlcnNpb247CisJX19sZTE2IHJlcG9ydF9kZXNjX2xlbjsKKwlfX2xlMTYgcmVwb3J0X2Rlc2Nf cmVnaXN0ZXI7CisJX19sZTE2IGlucHV0X3JlZ2lzdGVyOworCV9fbGUxNiBtYXhfaW5wdXRfbGVu OworCV9fbGUxNiBvdXRwdXRfcmVnaXN0ZXI7CisJX19sZTE2IG1heF9vdXRwdXRfbGVuOworCV9f bGUxNiBjb21tYW5kX3JlZ2lzdGVyOworCV9fbGUxNiBkYXRhX3JlZ2lzdGVyOworCV9fbGUxNiB2 ZW5kb3JfaWQ7CisJX19sZTE2IHByb2R1Y3RfaWQ7CisJX19sZTE2IHZlcnNpb25faWQ7CisJdTgg cmVzZXJ2ZWRbNF07Cit9IF9fcGFja2VkOworCitzdHJ1Y3QgY3l0dHNwNSB7CisJc3RydWN0IGRl dmljZSAqZGV2OworCXN0cnVjdCBjb21wbGV0aW9uIGNtZF9kb25lOworCXN0cnVjdCBjeXR0c3A1 X3N5c2luZm8gc3lzaW5mbzsKKwlzdHJ1Y3QgY3l0dHNwNV9oaWRfZGVzYyBoaWRfZGVzYzsKKwl1 OCBjbWRfYnVmW0NZVFRTUDVfUFJFQUxMT0NBVEVEX0NNRF9CVUZGRVJdOworCXU4IGlucHV0X2J1 ZltDWV9NQVhfSU5QVVRdOworCXU4IHJlc3BvbnNlX2J1ZltDWV9NQVhfSU5QVVRdOworCXN0cnVj dCBncGlvX2Rlc2MgKnJlc2V0X2dwaW87CisJc3RydWN0IGlucHV0X2RldiAqaW5wdXQ7CisJY2hh ciBwaHlzW05BTUVfTUFYXTsKKwlpbnQgbnVtX3Bydl9yZWM7CisJc3RydWN0IHJlZ21hcCAqcmVn bWFwOworCXN0cnVjdCB0b3VjaHNjcmVlbl9wcm9wZXJ0aWVzIHByb3A7CisJc3RydWN0IHJlZ3Vs YXRvciAqdmRkOworfTsKKworLyoKKyAqIEZvciB3aGF0IHVuZGVyc3Rvb2QgaW4gdGhlIGRhdGFz aGVldCwgdGhlIHJlZ2lzdGVyIGRvZXMgbm90CisgKiBtYXR0ZXIuIEZvciBjb25zaXN0ZW5jeSwg dXNlZCB0aGUgSW5wdXQgUmVnaXN0ZXIgYWRkcmVzcworICogYnV0IGl0IGRvZXMgbWVhbiBhbnl0 aGluZyB0byB0aGUgZGV2aWNlLiBUaGUgaW1wb3J0YW50IGRhdGEKKyAqIHRvIHNlbmQgaXMgdGhl IEkyQyBhZGRyZXNzCisgKi8KK3N0YXRpYyBpbnQgY3l0dHNwNV9yZWFkKHN0cnVjdCBjeXR0c3A1 ICp0cywgdTggKmJ1ZiwgdTMyIG1heCkKK3sKKwlpbnQgZXJyb3I7CisJdTMyIHNpemU7CisJdTgg dGVtcFsyXTsKKworCS8qIFJlYWQgdGhlIGZyYW1lIHRvIHJldHJpZXZlIHRoZSBzaXplICovCisJ ZXJyb3IgPSByZWdtYXBfYnVsa19yZWFkKHRzLT5yZWdtYXAsIEhJRF9JTlBVVF9SRUcsIHRlbXAs IHNpemVvZih0ZW1wKSk7CisJaWYgKGVycm9yKQorCQlyZXR1cm4gZXJyb3I7CisKKwlzaXplID0g Z2V0X3VuYWxpZ25lZF9sZTE2KHRlbXApOworCWlmICghc2l6ZSB8fCBzaXplID09IDIpCisJCXJl dHVybiAwOworCisJaWYgKHNpemUgPiBtYXgpCisJCXJldHVybiAtRUlOVkFMOworCisJLyogR2V0 IHRoZSByZWFsIHZhbHVlICovCisJcmV0dXJuIHJlZ21hcF9idWxrX3JlYWQodHMtPnJlZ21hcCwg SElEX0lOUFVUX1JFRywgYnVmLCBzaXplKTsKK30KKworc3RhdGljIGludCBjeXR0c3A1X3dyaXRl KHN0cnVjdCBjeXR0c3A1ICp0cywgdW5zaWduZWQgaW50IHJlZywgdTggKmRhdGEsCisJCQkgc2l6 ZV90IHNpemUpCit7CisJdTggY21kW0hJRF9PVVRQVVRfTUFYX0NNRF9TSVpFXTsKKworCWlmIChz aXplICsgMSA+IEhJRF9PVVRQVVRfTUFYX0NNRF9TSVpFKQorCQlyZXR1cm4gLUUyQklHOworCisJ LyogSGlnaCBieXRlcyBvZiByZWdpc3RlciBhZGRyZXNzIG5lZWRlZCBhcyBmaXJzdCBieXRlIG9m IGNtZCAqLworCWNtZFswXSA9IEhJX0JZVEUocmVnKTsKKworCS8qIENvcHkgdGhlIHJlc3Qgb2Yg dGhlIGRhdGEgKi8KKwlpZiAoZGF0YSkKKwkJbWVtY3B5KCZjbWRbMV0sIGRhdGEsIHNpemUpOwor CisJLyogVGhlIGhhcmR3YXJlIHdhbnRzIHRvIHJlY2VpdmUgYSBmcmFtZSB3aXRoIHRoZSBhZGRy ZXNzIHJlZ2lzdGVyCisJICogY29udGFpbnMgaW4gdGhlIGZpcnN0IHR3byBieXRlcy4gQXMgdGhl IHJlZ21hcF93cml0ZSBmdW5jdGlvbgorCSAqIGFkZCB0aGUgcmVnaXN0ZXIgYWRyZXNzZSBpbiB0 aGUgZnJhbWUsIHdlIHVzZSB0aGUgTE9XX0JZVEUgYXMKKwkgKiBmaXJzdCBmcmFtZSBieXRlIGZv ciB0aGUgYWRkcmVzcyByZWdpc3RlciBhbmQgdGhlIGZpcnN0CisJICogZGF0YSBieXRlIGlzIHRo ZSBoaWdoIHJlZ2lzdGVyICsgbGVmdCBvZiB0aGUgY21kIHRvIHNlbmQKKwkgKi8KKwlyZXR1cm4g cmVnbWFwX2J1bGtfd3JpdGUodHMtPnJlZ21hcCwgTE9XX0JZVEUocmVnKSwgY21kLCBzaXplICsg MSk7Cit9CisKK3N0YXRpYyB2b2lkIGN5dHRzcDVfZ2V0X3RvdWNoX2F4aXMoaW50ICpheGlzLCBp bnQgc2l6ZSwgaW50IG1heCwgdTggKnh5X2RhdGEsCisJCQkJICAgaW50IGJvZnMpCit7CisJaW50 IG5ieXRlOworCisJZm9yIChuYnl0ZSA9IDAsICpheGlzID0gMDsgbmJ5dGUgPCBzaXplOyBuYnl0 ZSsrKQorCQkqYXhpcyA9ICpheGlzICsgKCh4eV9kYXRhW25ieXRlXSA+PiBib2ZzKSA8PCAobmJ5 dGUgKiA4KSk7CisKKwkqYXhpcyAmPSBtYXggLSAxOworfQorCitzdGF0aWMgdm9pZCBjeXR0c3A1 X2dldF90b3VjaF9yZWNvcmQoc3RydWN0IGN5dHRzcDUgKnRzLAorCQkJCSAgICAgc3RydWN0IGN5 dHRzcDVfdG91Y2ggKnRvdWNoLCB1OCAqeHlfZGF0YSkKK3sKKwlzdHJ1Y3QgY3l0dHNwNV9zeXNp bmZvICpzaSA9ICZ0cy0+c3lzaW5mbzsKKwllbnVtIGN5dHRzcDVfdGNoX2FicyBhYnM7CisKKwlm b3IgKGFicyA9IENZX1RDSF9YOyBhYnMgPCBDWV9UQ0hfTlVNX0FCUzsgYWJzKyspCisJCWN5dHRz cDVfZ2V0X3RvdWNoX2F4aXMoJnRvdWNoLT5hYnNbYWJzXSwKKwkJCQkgICAgICAgc2ktPnRjaF9h YnNbYWJzXS5zaXplLAorCQkJCSAgICAgICBzaS0+dGNoX2Fic1thYnNdLm1heCwKKwkJCQkgICAg ICAgeHlfZGF0YSArIHNpLT50Y2hfYWJzW2Fic10ub2ZzLAorCQkJCSAgICAgICBzaS0+dGNoX2Fi c1thYnNdLmJvZnMpOworfQorCitzdGF0aWMgdm9pZCBjeXR0c3A1X2dldF9tdF90b3VjaGVzKHN0 cnVjdCBjeXR0c3A1ICp0cywKKwkJCQkgICBzdHJ1Y3QgY3l0dHNwNV90b3VjaCAqdGNoLCBpbnQg bnVtX2N1cl90Y2gpCit7CisJc3RydWN0IGN5dHRzcDVfc3lzaW5mbyAqc2kgPSAmdHMtPnN5c2lu Zm87CisJaW50IGksIHQgPSAwLCBvZmZzZXQgPSAwOworCURFQ0xBUkVfQklUTUFQKGlkcywgTUFY X0NZX1RDSF9UX0lEUyk7CisJdTggKnRjaF9hZGRyOworCWludCB0bXA7CisKKwliaXRtYXBfemVy byhpZHMsIE1BWF9DWV9UQ0hfVF9JRFMpOworCW1lbXNldCh0Y2gtPmFicywgMCwgc2l6ZW9mKHRj aC0+YWJzKSk7CisKKwlzd2l0Y2ggKHRzLT5pbnB1dF9idWZbMl0pIHsKKwljYXNlIEhJRF9UT1VD SF9SRVBPUlRfSUQ6CisJCW9mZnNldCA9IFRPVUNIX0lOUFVUX0hFQURFUl9TSVpFOworCQlicmVh azsKKwljYXNlIEhJRF9CVE5fUkVQT1JUX0lEOgorCQlvZmZzZXQgPSBCVE5fSU5QVVRfSEVBREVS X1NJWkU7CisJCWJyZWFrOworCX0KKworCWZvciAoaSA9IDA7IGkgPCBudW1fY3VyX3RjaDsgaSsr KSB7CisJCXRjaF9hZGRyID0gdHMtPmlucHV0X2J1ZiArIG9mZnNldCArIChpICogVE9VQ0hfUkVQ T1JUX1NJWkUpOworCQljeXR0c3A1X2dldF90b3VjaF9yZWNvcmQodHMsIHRjaCwgdGNoX2FkZHIp OworCisJCS8qIENvbnZlcnQgTUFKT1IvTUlOT1IgZnJvbSBtbSB0byByZXNvbHV0aW9uICovCisJ CXRtcCA9IHRjaC0+YWJzW0NZX1RDSF9NQUpdICogMTAwICogc2ktPnNlbnNpbmdfY29uZl9kYXRh LnJlc194OworCQl0Y2gtPmFic1tDWV9UQ0hfTUFKXSA9IHRtcCAvIHNpLT5zZW5zaW5nX2NvbmZf ZGF0YS5sZW5feDsKKwkJdG1wID0gdGNoLT5hYnNbQ1lfVENIX01JTl0gKiAxMDAgKiBzaS0+c2Vu c2luZ19jb25mX2RhdGEucmVzX3g7CisJCXRjaC0+YWJzW0NZX1RDSF9NSU5dID0gdG1wIC8gc2kt PnNlbnNpbmdfY29uZl9kYXRhLmxlbl94OworCisJCXQgPSB0Y2gtPmFic1tDWV9UQ0hfVF07CisJ CWlucHV0X210X3Nsb3QodHMtPmlucHV0LCB0KTsKKwkJaW5wdXRfbXRfcmVwb3J0X3Nsb3Rfc3Rh dGUodHMtPmlucHV0LCBNVF9UT09MX0ZJTkdFUiwgdHJ1ZSk7CisJCV9fc2V0X2JpdCh0LCBpZHMp OworCisJCS8qIHBvc2l0aW9uIGFuZCBwcmVzc3VyZSBmaWVsZHMgKi8KKwkJdG91Y2hzY3JlZW5f cmVwb3J0X3Bvcyh0cy0+aW5wdXQsICZ0cy0+cHJvcCwKKwkJCQkgICAgICAgdGNoLT5hYnNbQ1lf VENIX1hdLCB0Y2gtPmFic1tDWV9UQ0hfWV0sCisJCQkJICAgICAgIHRydWUpOworCQlpbnB1dF9y ZXBvcnRfYWJzKHRzLT5pbnB1dCwgQUJTX01UX1BSRVNTVVJFLAorCQkJCSB0Y2gtPmFic1tDWV9U Q0hfUF0pOworCisJCS8qIEdldCB0aGUgZXh0ZW5kZWQgdG91Y2ggZmllbGRzICovCisJCWlucHV0 X3JlcG9ydF9hYnModHMtPmlucHV0LCBBQlNfTVRfVE9VQ0hfTUFKT1IsCisJCQkJIHRjaC0+YWJz W0NZX1RDSF9NQUpdKTsKKwkJaW5wdXRfcmVwb3J0X2Ficyh0cy0+aW5wdXQsIEFCU19NVF9UT1VD SF9NSU5PUiwKKwkJCQkgdGNoLT5hYnNbQ1lfVENIX01JTl0pOworCX0KKworCXRzLT5udW1fcHJ2 X3JlYyA9IG51bV9jdXJfdGNoOworfQorCitzdGF0aWMgaW50IGN5dHRzcDVfbXRfYXR0ZW50aW9u KHN0cnVjdCBkZXZpY2UgKmRldikKK3sKKwlzdHJ1Y3QgY3l0dHNwNSAqdHMgPSBkZXZfZ2V0X2Ry dmRhdGEoZGV2KTsKKwlzdHJ1Y3QgY3l0dHNwNV9zeXNpbmZvICpzaSA9ICZ0cy0+c3lzaW5mbzsK KwlpbnQgbWF4X3RjaCA9IHNpLT5zZW5zaW5nX2NvbmZfZGF0YS5tYXhfdGNoOworCXN0cnVjdCBj eXR0c3A1X3RvdWNoIHRjaDsKKwl1OCBudW1fY3VyX3RjaDsKKworCWN5dHRzcDVfZ2V0X3RvdWNo X2F4aXMoKGludCAqKSAmbnVtX2N1cl90Y2gsIHNpLT50Y2hfaGRyLnNpemUsCisJCQkgICAgICAg c2ktPnRjaF9oZHIubWF4LAorCQkJICAgICAgIHRzLT5pbnB1dF9idWYgKyAzICsgc2ktPnRjaF9o ZHIub2ZzLAorCQkJICAgICAgIHNpLT50Y2hfaGRyLmJvZnMpOworCisJaWYgKG51bV9jdXJfdGNo ID4gbWF4X3RjaCkgeworCQlkZXZfZXJyKGRldiwgIk51bSB0b3VjaCBlcnIgZGV0ZWN0ZWQgKG49 JWQpXG4iLCBudW1fY3VyX3RjaCk7CisJCW51bV9jdXJfdGNoID0gbWF4X3RjaDsKKwl9CisKKwlp ZiAobnVtX2N1cl90Y2ggPT0gMCAmJiB0cy0+bnVtX3Bydl9yZWMgPT0gMCkKKwkJcmV0dXJuIDA7 CisKKwkvKiBleHRyYWN0IHh5X2RhdGEgZm9yIGFsbCBjdXJyZW50bHkgcmVwb3J0ZWQgdG91Y2hl cyAqLworCWlmIChudW1fY3VyX3RjaCkKKwkJY3l0dHNwNV9nZXRfbXRfdG91Y2hlcyh0cywgJnRj aCwgbnVtX2N1cl90Y2gpOworCisJaW5wdXRfbXRfc3luY19mcmFtZSh0cy0+aW5wdXQpOworCWlu cHV0X3N5bmModHMtPmlucHV0KTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IGN5dHRz cDVfc2V0dXBfaW5wdXRfZGV2aWNlKHN0cnVjdCBkZXZpY2UgKmRldikKK3sKKwlzdHJ1Y3QgY3l0 dHNwNSAqdHMgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKKwlzdHJ1Y3QgY3l0dHNwNV9zeXNpbmZv ICpzaSA9ICZ0cy0+c3lzaW5mbzsKKwlpbnQgbWF4X3gsIG1heF95LCBtYXhfcDsKKwlpbnQgbWF4 X3hfdG1wLCBtYXhfeV90bXA7CisJaW50IGVycm9yOworCisJbWF4X3hfdG1wID0gc2ktPnNlbnNp bmdfY29uZl9kYXRhLnJlc194OworCW1heF95X3RtcCA9IHNpLT5zZW5zaW5nX2NvbmZfZGF0YS5y ZXNfeTsKKwltYXhfeCA9IG1heF94X3RtcCAtIDE7CisJbWF4X3kgPSBtYXhfeV90bXAgLSAxOwor CW1heF9wID0gc2ktPnNlbnNpbmdfY29uZl9kYXRhLm1heF96OworCisJaW5wdXRfc2V0X2Fic19w YXJhbXModHMtPmlucHV0LCBBQlNfTVRfUE9TSVRJT05fWCwgMCwgbWF4X3gsIDAsIDApOworCWlu cHV0X3NldF9hYnNfcGFyYW1zKHRzLT5pbnB1dCwgQUJTX01UX1BPU0lUSU9OX1ksIDAsIG1heF95 LCAwLCAwKTsKKwlpbnB1dF9zZXRfYWJzX3BhcmFtcyh0cy0+aW5wdXQsIEFCU19NVF9QUkVTU1VS RSwgMCwgbWF4X3AsIDAsIDApOworCisJaW5wdXRfc2V0X2Fic19wYXJhbXModHMtPmlucHV0LCBB QlNfTVRfVE9VQ0hfTUFKT1IsIDAsIE1BWF9BUkVBLCAwLCAwKTsKKwlpbnB1dF9zZXRfYWJzX3Bh cmFtcyh0cy0+aW5wdXQsIEFCU19NVF9UT1VDSF9NSU5PUiwgMCwgTUFYX0FSRUEsIDAsIDApOwor CisJZXJyb3IgPSBpbnB1dF9tdF9pbml0X3Nsb3RzKHRzLT5pbnB1dCwgc2ktPnRjaF9hYnNbQ1lf VENIX1RdLm1heCwKKwkJSU5QVVRfTVRfRFJPUF9VTlVTRUQgfCBJTlBVVF9NVF9ESVJFQ1QpOwor CWlmIChlcnJvciA8IDApCisJCXJldHVybiBlcnJvcjsKKworCWVycm9yID0gaW5wdXRfcmVnaXN0 ZXJfZGV2aWNlKHRzLT5pbnB1dCk7CisJaWYgKGVycm9yIDwgMCkKKwkJZGV2X2VycihkZXYsICJF cnJvciwgZmFpbGVkIHJlZ2lzdGVyIGlucHV0IGRldmljZSByPSVkXG4iLCBlcnJvcik7CisKKwly ZXR1cm4gZXJyb3I7Cit9CisKK3N0YXRpYyBpbnQgY3l0dHNwNV9wYXJzZV9kdF9rZXlfY29kZShz dHJ1Y3QgZGV2aWNlICpkZXYpCit7CisJc3RydWN0IGN5dHRzcDUgKnRzID0gZGV2X2dldF9kcnZk YXRhKGRldik7CisJc3RydWN0IGN5dHRzcDVfc3lzaW5mbyAqc2kgPSAmdHMtPnN5c2luZm87CisJ aW50IGk7CisKKwlpZiAoIXNpLT5udW1fYnRucykKKwkJcmV0dXJuIDA7CisKKwkvKiBJbml0aWFs aXplIHRoZSBidXR0b24gdG8gUkVTRVJWRUQgKi8KKwlmb3IgKGkgPSAwOyBpIDwgc2ktPm51bV9i dG5zOyBpKyspCisJCXNpLT5rZXlfY29kZVtpXSA9IEtFWV9SRVNFUlZFRDsKKworCXJldHVybiBk ZXZpY2VfcHJvcGVydHlfcmVhZF91MzJfYXJyYXkoZGV2LCAibGludXgsa2V5Y29kZXMiLAorCQkJ CSAgIHNpLT5rZXlfY29kZSwgc2ktPm51bV9idG5zKTsKK30KKworc3RhdGljIGludCBjeXR0c3A1 X2J0bl9hdHRlbnRpb24oc3RydWN0IGRldmljZSAqZGV2KQoreworCXN0cnVjdCBjeXR0c3A1ICp0 cyA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOworCXN0cnVjdCBjeXR0c3A1X3N5c2luZm8gKnNpID0g JnRzLT5zeXNpbmZvOworCWludCBjdXJfYnRuLCBvZmZzZXQgPSAwOworCWludCBjdXJfYnRuX3N0 YXRlOworCisJc3dpdGNoICh0cy0+aW5wdXRfYnVmWzJdKSB7CisJY2FzZSBISURfVE9VQ0hfUkVQ T1JUX0lEOgorCQlvZmZzZXQgPSBUT1VDSF9JTlBVVF9IRUFERVJfU0laRTsKKwkJYnJlYWs7CisJ Y2FzZSBISURfQlROX1JFUE9SVF9JRDoKKwkJb2Zmc2V0ID0gQlROX0lOUFVUX0hFQURFUl9TSVpF OworCQlicmVhazsKKwl9CisKKwlpZiAodHMtPmlucHV0X2J1ZlsyXSAhPSBISURfQlROX1JFUE9S VF9JRCB8fCAhc2ktPm51bV9idG5zKQorCQlyZXR1cm4gMDsKKworCS8qIGV4dHJhY3QgYnV0dG9u IHByZXNzL3JlbGVhc2UgdG91Y2ggaW5mb3JtYXRpb24gKi8KKwlmb3IgKGN1cl9idG4gPSAwOyBj dXJfYnRuIDwgc2ktPm51bV9idG5zOyBjdXJfYnRuKyspIHsKKwkJLyogR2V0IGN1cnJlbnQgYnV0 dG9uIHN0YXRlICovCisJCWN1cl9idG5fc3RhdGUgPSAodHMtPmlucHV0X2J1ZltvZmZzZXRdID4+ IChjdXJfYnRuICogQ1lfQklUU19QRVJfQlROKSkKKwkJCSYgQ1lfTlVNX0JUTl9FVkVOVF9JRDsK KworCQlpbnB1dF9yZXBvcnRfa2V5KHRzLT5pbnB1dCwgc2ktPmtleV9jb2RlW2N1cl9idG5dLAor CQkJCSBjdXJfYnRuX3N0YXRlKTsKKwkJaW5wdXRfc3luYyh0cy0+aW5wdXQpOworCX0KKworCXJl dHVybiAwOworfQorCitzdGF0aWMgaW50IGN5dHRzcDVfdmFsaWRhdGVfY21kX3Jlc3BvbnNlKHN0 cnVjdCBjeXR0c3A1ICp0cywgdTggY29kZSkKK3sKKwl1MTYgc2l6ZSwgY3JjOworCXU4IHN0YXR1 cywgcmVwb3J0X2lkOworCWludCBjb21tYW5kX2NvZGU7CisKKwlzaXplID0gZ2V0X3VuYWxpZ25l ZF9sZTE2KCZ0cy0+cmVzcG9uc2VfYnVmWzBdKTsKKworCWlmICghc2l6ZSkKKwkJcmV0dXJuIDA7 CisKKwlyZXBvcnRfaWQgPSB0cy0+cmVzcG9uc2VfYnVmW0hJRF9PVVRQVVRfUkVTUE9OU0VfUkVQ T1JUX09GRlNFVF07CisKKwlzd2l0Y2ggKHJlcG9ydF9pZCkgeworCWNhc2UgSElEX0JMX1JFU1BP TlNFX1JFUE9SVF9JRDogeworCQlpZiAodHMtPnJlc3BvbnNlX2J1Zls0XSAhPSBISURfT1VUUFVU X0JMX1NPUCkgeworCQkJZGV2X2Vycih0cy0+ZGV2LCAiSElEIG91dHB1dCByZXNwb25zZSwgd3Jv bmcgU09QXG4iKTsKKwkJCXJldHVybiAtRVBST1RPOworCQl9CisKKwkJaWYgKHRzLT5yZXNwb25z ZV9idWZbc2l6ZSAtIDFdICE9IEhJRF9PVVRQVVRfQkxfRU9QKSB7CisJCQlkZXZfZXJyKHRzLT5k ZXYsICJISUQgb3V0cHV0IHJlc3BvbnNlLCB3cm9uZyBFT1BcbiIpOworCQkJcmV0dXJuIC1FUFJP VE87CisJCX0KKworCQljcmMgPSBjcmNfaXR1X3QoMHhGRkZGLCAmdHMtPnJlc3BvbnNlX2J1Zls0 XSwgc2l6ZSAtIDcpOworCQlpZiAodHMtPnJlc3BvbnNlX2J1ZltzaXplIC0gM10gIT0gTE9XX0JZ VEUoY3JjKSB8fAorCQkgICAgdHMtPnJlc3BvbnNlX2J1ZltzaXplIC0gMl0gIT0gSElfQllURShj cmMpKSB7CisJCQlkZXZfZXJyKHRzLT5kZXYsICJISUQgb3V0cHV0IHJlc3BvbnNlLCB3cm9uZyBD UkMgMHglWFxuIiwKKwkJCQljcmMpOworCQkJcmV0dXJuIC1FUFJPVE87CisJCX0KKworCQlzdGF0 dXMgPSB0cy0+cmVzcG9uc2VfYnVmWzVdOworCQlpZiAoc3RhdHVzKSB7CisJCQlkZXZfZXJyKHRz LT5kZXYsICJISUQgb3V0cHV0IHJlc3BvbnNlLCBFUlJPUjolZFxuIiwKKwkJCQlzdGF0dXMpOwor CQkJcmV0dXJuIC1FUFJPVE87CisJCX0KKwkJYnJlYWs7CisJfQorCWNhc2UgSElEX0FQUF9SRVNQ T05TRV9SRVBPUlRfSUQ6IHsKKwkJY29tbWFuZF9jb2RlID0gdHMtPnJlc3BvbnNlX2J1ZltISURf T1VUUFVUX1JFU1BPTlNFX0NNRF9PRkZTRVRdCisJCQkmIEhJRF9PVVRQVVRfUkVTUE9OU0VfQ01E X01BU0s7CisJCWlmIChjb21tYW5kX2NvZGUgIT0gY29kZSkgeworCQkJZGV2X2Vycih0cy0+ZGV2 LAorCQkJCSJISUQgb3V0cHV0IHJlc3BvbnNlLCB3cm9uZyBjb21tYW5kX2NvZGU6JVhcbiIsCisJ CQkJY29tbWFuZF9jb2RlKTsKKwkJCXJldHVybiAtRVBST1RPOworCQl9CisJCWJyZWFrOworCX0K Kwl9CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIHZvaWQgY3l0dHNwNV9zaV9nZXRfYnRuX2Rh dGEoc3RydWN0IGN5dHRzcDUgKnRzKQoreworCXN0cnVjdCBjeXR0c3A1X3N5c2luZm8gKnNpID0g JnRzLT5zeXNpbmZvOworCXVuc2lnbmVkIGludCBidG5zID0gdHMtPnJlc3BvbnNlX2J1ZltISURf U1lTSU5GT19CVE5fT0ZGU0VUXQorCQkmIEhJRF9TWVNJTkZPX0JUTl9NQVNLOworCisJc2ktPm51 bV9idG5zID0gaHdlaWdodDgoYnRucyk7Cit9CisKK3N0YXRpYyBpbnQgY3l0dHNwNV9nZXRfc3lz aW5mb19yZWdzKHN0cnVjdCBjeXR0c3A1ICp0cykKK3sKKwlzdHJ1Y3QgY3l0dHNwNV9zZW5zaW5n X2NvbmZfZGF0YSAqc2NkID0gJnRzLT5zeXNpbmZvLnNlbnNpbmdfY29uZl9kYXRhOworCXN0cnVj dCBjeXR0c3A1X3NlbnNpbmdfY29uZl9kYXRhX2RldiAqc2NkX2RldiA9CisJCShzdHJ1Y3QgY3l0 dHNwNV9zZW5zaW5nX2NvbmZfZGF0YV9kZXYgKikKKwkJJnRzLT5yZXNwb25zZV9idWZbSElEX1NZ U0lORk9fU0VOU0lOR19PRkZTRVRdOworCisJY3l0dHNwNV9zaV9nZXRfYnRuX2RhdGEodHMpOwor CisJc2NkLT5tYXhfdGNoID0gc2NkX2Rldi0+bWF4X251bV9vZl90Y2hfcGVyX3JlZnJlc2hfY3lj bGU7CisJc2NkLT5yZXNfeCA9IGdldF91bmFsaWduZWRfbGUxNigmc2NkX2Rldi0+cmVzX3gpOwor CXNjZC0+cmVzX3kgPSBnZXRfdW5hbGlnbmVkX2xlMTYoJnNjZF9kZXYtPnJlc195KTsKKwlzY2Qt Pm1heF96ID0gZ2V0X3VuYWxpZ25lZF9sZTE2KCZzY2RfZGV2LT5tYXhfeik7CisJc2NkLT5sZW5f eCA9IGdldF91bmFsaWduZWRfbGUxNigmc2NkX2Rldi0+bGVuX3gpOworCXNjZC0+bGVuX3kgPSBn ZXRfdW5hbGlnbmVkX2xlMTYoJnNjZF9kZXYtPmxlbl95KTsKKworCXJldHVybiAwOworfQorCitz dGF0aWMgaW50IGN5dHRzcDVfaGlkX291dHB1dF9nZXRfc3lzaW5mbyhzdHJ1Y3QgY3l0dHNwNSAq dHMpCit7CisJaW50IHJjOworCXU4IGNtZFtISURfT1VUUFVUX0dFVF9TWVNJTkZPX1NJWkVdOwor CisJLyogSEkgYnl0ZXMgb2YgT3V0cHV0IHJlZ2lzdGVyIGFkZHJlc3MgKi8KKwljbWRbMF0gPSBM T1dfQllURShISURfT1VUUFVUX0dFVF9TWVNJTkZPX1NJWkUpOworCWNtZFsxXSA9IEhJX0JZVEUo SElEX09VVFBVVF9HRVRfU1lTSU5GT19TSVpFKTsKKwljbWRbMl0gPSBISURfQVBQX09VVFBVVF9S RVBPUlRfSUQ7CisJY21kWzNdID0gMHgwOyAvKiBSZXNlcnZlZCAqLworCWNtZFs0XSA9IEhJRF9P VVRQVVRfR0VUX1NZU0lORk87CisKKwlyYyA9IGN5dHRzcDVfd3JpdGUodHMsIEhJRF9PVVRQVVRf UkVHLCBjbWQsCisJCQkgICBISURfT1VUUFVUX0dFVF9TWVNJTkZPX1NJWkUpOworCWlmIChyYykg eworCQlkZXZfZXJyKHRzLT5kZXYsICJGYWlsZWQgdG8gd3JpdGUgY29tbWFuZCAlZCIsIHJjKTsK KwkJcmV0dXJuIHJjOworCX0KKworCXJjID0gd2FpdF9mb3JfY29tcGxldGlvbl9pbnRlcnJ1cHRp YmxlX3RpbWVvdXQoJnRzLT5jbWRfZG9uZSwKKwkJCQkJCW1zZWNzX3RvX2ppZmZpZXMoQ1lfSElE X09VVFBVVF9HRVRfU1lTSU5GT19USU1FT1VUKSk7CisJaWYgKHJjIDw9IDApIHsKKwkJZGV2X2Vy cih0cy0+ZGV2LCAiSElEIG91dHB1dCBjbWQgZXhlY3V0aW9uIHRpbWVkIG91dFxuIik7CisJCXJj ID0gLUVUSU1FOworCQlyZXR1cm4gcmM7CisJfQorCisJcmMgPSBjeXR0c3A1X3ZhbGlkYXRlX2Nt ZF9yZXNwb25zZSh0cywgSElEX09VVFBVVF9HRVRfU1lTSU5GTyk7CisJaWYgKHJjKSB7CisJCWRl dl9lcnIodHMtPmRldiwgIlZhbGlkYXRpb24gb2YgdGhlIHJlc3BvbnNlIGZhaWxlZFxuIik7CisJ CXJldHVybiByYzsKKwl9CisKKwlyZXR1cm4gY3l0dHNwNV9nZXRfc3lzaW5mb19yZWdzKHRzKTsK K30KKworc3RhdGljIGludCBjeXR0c3A1X2hpZF9vdXRwdXRfYmxfbGF1bmNoX2FwcChzdHJ1Y3Qg Y3l0dHNwNSAqdHMpCit7CisJaW50IHJjOworCXU4IGNtZFtISURfT1VUUFVUX0JMX0xBVU5DSF9B UFBdOworCXUxNiBjcmM7CisKKwljbWRbMF0gPSBMT1dfQllURShISURfT1VUUFVUX0JMX0xBVU5D SF9BUFBfU0laRSk7CisJY21kWzFdID0gSElfQllURShISURfT1VUUFVUX0JMX0xBVU5DSF9BUFBf U0laRSk7CisJY21kWzJdID0gSElEX0JMX09VVFBVVF9SRVBPUlRfSUQ7CisJY21kWzNdID0gMHgw OyAvKiBSZXNlcnZlZCAqLworCWNtZFs0XSA9IEhJRF9PVVRQVVRfQkxfU09QOworCWNtZFs1XSA9 IEhJRF9PVVRQVVRfQkxfTEFVTkNIX0FQUDsKKwljbWRbNl0gPSAweDA7IC8qIExvdyBieXRlcyBv ZiBkYXRhICovCisJY21kWzddID0gMHgwOyAvKiBIaSBieXRlcyBvZiBkYXRhICovCisJY3JjID0g Y3JjX2l0dV90KDB4RkZGRiwgJmNtZFs0XSwgNCk7CisJY21kWzhdID0gTE9XX0JZVEUoY3JjKTsK KwljbWRbOV0gPSBISV9CWVRFKGNyYyk7CisJY21kWzEwXSA9IEhJRF9PVVRQVVRfQkxfRU9QOwor CisJcmMgPSBjeXR0c3A1X3dyaXRlKHRzLCBISURfT1VUUFVUX1JFRywgY21kLAorCQkJICAgSElE X09VVFBVVF9CTF9MQVVOQ0hfQVBQX1NJWkUpOworCWlmIChyYykgeworCQlkZXZfZXJyKHRzLT5k ZXYsICJGYWlsZWQgdG8gd3JpdGUgY29tbWFuZCAlZCIsIHJjKTsKKwkJcmV0dXJuIHJjOworCX0K KworCXJjID0gd2FpdF9mb3JfY29tcGxldGlvbl9pbnRlcnJ1cHRpYmxlX3RpbWVvdXQoJnRzLT5j bWRfZG9uZSwKKwkJCQkJCW1zZWNzX3RvX2ppZmZpZXMoQ1lfSElEX09VVFBVVF9USU1FT1VUKSk7 CisJaWYgKHJjIDw9IDApIHsKKwkJZGV2X2Vycih0cy0+ZGV2LCAiSElEIG91dHB1dCBjbWQgZXhl Y3V0aW9uIHRpbWVkIG91dFxuIik7CisJCXJjID0gLUVUSU1FOworCQlyZXR1cm4gcmM7CisJfQor CisJcmMgPSBjeXR0c3A1X3ZhbGlkYXRlX2NtZF9yZXNwb25zZSh0cywgSElEX09VVFBVVF9CTF9M QVVOQ0hfQVBQKTsKKwlpZiAocmMpIHsKKwkJZGV2X2Vycih0cy0+ZGV2LCAiVmFsaWRhdGlvbiBv ZiB0aGUgcmVzcG9uc2UgZmFpbGVkXG4iKTsKKwkJcmV0dXJuIHJjOworCX0KKworCXJldHVybiAw OworfQorCitzdGF0aWMgaW50IGN5dHRzcDVfZ2V0X2hpZF9kZXNjcmlwdG9yKHN0cnVjdCBjeXR0 c3A1ICp0cywKKwkJCQkgICAgICBzdHJ1Y3QgY3l0dHNwNV9oaWRfZGVzYyAqZGVzYykKK3sKKwlz dHJ1Y3QgZGV2aWNlICpkZXYgPSB0cy0+ZGV2OworCV9fbGUxNiBoaWRfZGVzY19yZWdpc3RlciA9 IEhJRF9ERVNDX1JFRzsKKwlpbnQgcmM7CisJdTggY21kWzJdOworCisJLyogU2V0IEhJRCBkZXNj cmlwdG9yIHJlZ2lzdGVyICovCisJbWVtY3B5KGNtZCwgJmhpZF9kZXNjX3JlZ2lzdGVyLCBzaXpl b2YoaGlkX2Rlc2NfcmVnaXN0ZXIpKTsKKworCXJjID0gY3l0dHNwNV93cml0ZSh0cywgSElEX0RF U0NfUkVHLCBOVUxMLCAwKTsKKwlpZiAocmMpIHsKKwkJZGV2X2VycihkZXYsICJGYWlsZWQgdG8g Z2V0IEhJRCBkZXNjcmlwdG9yLCByYz0lZFxuIiwgcmMpOworCQlyZXR1cm4gcmM7CisJfQorCisJ cmMgPSB3YWl0X2Zvcl9jb21wbGV0aW9uX2ludGVycnVwdGlibGVfdGltZW91dCgmdHMtPmNtZF9k b25lLAorCQkJCQkJbXNlY3NfdG9famlmZmllcyhDWV9ISURfR0VUX0hJRF9ERVNDUklQVE9SX1RJ TUVPVVQpKTsKKwlpZiAocmMgPD0gMCkgeworCQlkZXZfZXJyKHRzLT5kZXYsICJISUQgZ2V0IGRl c2NyaXB0b3IgdGltZWQgb3V0XG4iKTsKKwkJcmMgPSAtRVRJTUU7CisJCXJldHVybiByYzsKKwl9 CisKKwltZW1jcHkoZGVzYywgdHMtPnJlc3BvbnNlX2J1Ziwgc2l6ZW9mKHN0cnVjdCBjeXR0c3A1 X2hpZF9kZXNjKSk7CisKKwkvKiBDaGVjayBISUQgZGVzY3JpcHRvciBsZW5ndGggYW5kIHZlcnNp b24gKi8KKwlpZiAobGUxNl90b19jcHUoZGVzYy0+aGlkX2Rlc2NfbGVuKSAhPSBzaXplb2YoKmRl c2MpIHx8CisJICAgIGxlMTZfdG9fY3B1KGRlc2MtPmJjZF92ZXJzaW9uKSAhPSBISURfVkVSU0lP TikgeworCQlkZXZfZXJyKGRldiwgIlVuc3VwcG9ydGVkIEhJRCB2ZXJzaW9uXG4iKTsKKwkJcmV0 dXJuIC1FTk9ERVY7CisJfQorCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgZmlsbF90Y2hf YWJzKHN0cnVjdCBjeXR0c3A1X3RjaF9hYnNfcGFyYW1zICp0Y2hfYWJzLCBpbnQgcmVwb3J0X3Np emUsCisJCQlpbnQgb2Zmc2V0KQoreworCXRjaF9hYnMtPm9mcyA9IG9mZnNldCAvIDg7CisJdGNo X2Ficy0+c2l6ZSA9IHJlcG9ydF9zaXplIC8gODsKKwlpZiAocmVwb3J0X3NpemUgJSA4KQorCQl0 Y2hfYWJzLT5zaXplICs9IDE7CisJdGNoX2Ficy0+bWluID0gMDsKKwl0Y2hfYWJzLT5tYXggPSAx IDw8IHJlcG9ydF9zaXplOworCXRjaF9hYnMtPmJvZnMgPSBvZmZzZXQgLSAodGNoX2Ficy0+b2Zz IDw8IDMpOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpcnFyZXR1cm5fdCBjeXR0c3A1X2hh bmRsZV9pcnEoaW50IGlycSwgdm9pZCAqaGFuZGxlKQoreworCXN0cnVjdCBjeXR0c3A1ICp0cyA9 IGhhbmRsZTsKKwlpbnQgcmVwb3J0X2lkOworCWludCBzaXplOworCWludCBlcnJvcjsKKworCWVy cm9yID0gY3l0dHNwNV9yZWFkKHRzLCB0cy0+aW5wdXRfYnVmLCBDWV9NQVhfSU5QVVQpOworCWlm IChlcnJvcikKKwkJcmV0dXJuIElSUV9IQU5ETEVEOworCisJc2l6ZSA9IGdldF91bmFsaWduZWRf bGUxNigmdHMtPmlucHV0X2J1ZlswXSk7CisKKwlpZiAoc2l6ZSA9PSAwKSB7CisJCS8qIHJlc2V0 ICovCisJCXJlcG9ydF9pZCA9IDA7CisJCXNpemUgPSAyOworCX0gZWxzZSB7CisJCXJlcG9ydF9p ZCA9IHRzLT5pbnB1dF9idWZbMl07CisJfQorCisJc3dpdGNoIChyZXBvcnRfaWQpIHsKKwljYXNl IEhJRF9UT1VDSF9SRVBPUlRfSUQ6CisJCWN5dHRzcDVfbXRfYXR0ZW50aW9uKHRzLT5kZXYpOwor CQlicmVhazsKKwljYXNlIEhJRF9CVE5fUkVQT1JUX0lEOgorCQljeXR0c3A1X2J0bl9hdHRlbnRp b24odHMtPmRldik7CisJCWJyZWFrOworCWRlZmF1bHQ6CisJCS8qIEl0IGlzIG5vdCBhbiBpbnB1 dCBidXQgYSBjb21tYW5kIHJlc3BvbnNlICovCisJCW1lbWNweSh0cy0+cmVzcG9uc2VfYnVmLCB0 cy0+aW5wdXRfYnVmLCBzaXplKTsKKwkJY29tcGxldGUoJnRzLT5jbWRfZG9uZSk7CisJfQorCisJ cmV0dXJuIElSUV9IQU5ETEVEOworfQorCitzdGF0aWMgaW50IGN5dHRzcDVfZGVhc3NlcnRfaW50 KHN0cnVjdCBjeXR0c3A1ICp0cykKK3sKKwl1MTYgc2l6ZTsKKwl1OCBidWZbMl07CisJaW50IGVy cm9yOworCisJZXJyb3IgPSByZWdtYXBfYnVsa19yZWFkKHRzLT5yZWdtYXAsIEhJRF9JTlBVVF9S RUcsIGJ1ZiwgMik7CisJaWYgKGVycm9yIDwgMCkKKwkJcmV0dXJuIGVycm9yOworCisJc2l6ZSA9 IGdldF91bmFsaWduZWRfbGUxNigmYnVmWzBdKTsKKwlpZiAoc2l6ZSA9PSAyIHx8IHNpemUgPT0g MCkKKwkJcmV0dXJuIDA7CisKKwlyZXR1cm4gLUVJTlZBTDsKK30KKworc3RhdGljIGludCBjeXR0 c3A1X2ZpbGxfYWxsX3RvdWNoKHN0cnVjdCBjeXR0c3A1ICp0cykKK3sKKwlzdHJ1Y3QgY3l0dHNw NV9zeXNpbmZvICpzaSA9ICZ0cy0+c3lzaW5mbzsKKworCWZpbGxfdGNoX2Ficygmc2ktPnRjaF9h YnNbQ1lfVENIX1hdLCBSRVBPUlRfU0laRV8xNiwKKwkJICAgICBUT1VDSF9SRVBPUlRfREVTQ19Y KTsKKwlmaWxsX3RjaF9hYnMoJnNpLT50Y2hfYWJzW0NZX1RDSF9ZXSwgUkVQT1JUX1NJWkVfMTYs CisJCSAgICAgVE9VQ0hfUkVQT1JUX0RFU0NfWSk7CisJZmlsbF90Y2hfYWJzKCZzaS0+dGNoX2Fi c1tDWV9UQ0hfUF0sIFJFUE9SVF9TSVpFXzgsCisJCSAgICAgVE9VQ0hfUkVQT1JUX0RFU0NfUCk7 CisJZmlsbF90Y2hfYWJzKCZzaS0+dGNoX2Fic1tDWV9UQ0hfVF0sIFJFUE9SVF9TSVpFXzUsCisJ CSAgICAgVE9VQ0hfUkVQT1JUX0RFU0NfQ09OVEFDVElEKTsKKwlmaWxsX3RjaF9hYnMoJnNpLT50 Y2hfaGRyLCBSRVBPUlRfU0laRV81LAorCQkgICAgIFRPVUNIX1JFUE9SVF9ERVNDX0hEUl9DT05U QUNUQ09VTlQpOworCWZpbGxfdGNoX2Ficygmc2ktPnRjaF9hYnNbQ1lfVENIX01BSl0sIFJFUE9S VF9TSVpFXzgsCisJCSAgICAgVE9VQ0hfUkVQT1JUX0RFU0NfTUFKKTsKKwlmaWxsX3RjaF9hYnMo JnNpLT50Y2hfYWJzW0NZX1RDSF9NSU5dLCBSRVBPUlRfU0laRV84LAorCQkgICAgIFRPVUNIX1JF UE9SVF9ERVNDX01JTik7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBjeXR0c3A1X3N0 YXJ0dXAoc3RydWN0IGN5dHRzcDUgKnRzKQoreworCWludCBlcnJvcjsKKworCWVycm9yID0gY3l0 dHNwNV9kZWFzc2VydF9pbnQodHMpOworCWlmIChlcnJvcikgeworCQlkZXZfZXJyKHRzLT5kZXYs ICJFcnJvciBvbiBkZWFzc2VydCBpbnQgcj0lZFxuIiwgZXJyb3IpOworCQlyZXR1cm4gLUVOT0RF VjsKKwl9CisKKwkvKgorCSAqIExhdW5jaCB0aGUgYXBwbGljYXRpb24gYXMgdGhlIGRldmljZSBz dGFydHMgaW4gYm9vdGxvYWRlciBtb2RlCisJICogYmVjYXVzZSBvZiBhIHBvd2VyLW9uLXJlc2V0 CisJICovCisJZXJyb3IgPSBjeXR0c3A1X2hpZF9vdXRwdXRfYmxfbGF1bmNoX2FwcCh0cyk7CisJ aWYgKGVycm9yIDwgMCkgeworCQlkZXZfZXJyKHRzLT5kZXYsICJFcnJvciBvbiBsYXVuY2ggYXBw IHI9JWRcbiIsIGVycm9yKTsKKwkJcmV0dXJuIGVycm9yOworCX0KKworCWVycm9yID0gY3l0dHNw NV9nZXRfaGlkX2Rlc2NyaXB0b3IodHMsICZ0cy0+aGlkX2Rlc2MpOworCWlmIChlcnJvciA8IDAp IHsKKwkJZGV2X2Vycih0cy0+ZGV2LCAiRXJyb3Igb24gZ2V0dGluZyBISUQgZGVzY3JpcHRvciBy PSVkXG4iLCBlcnJvcik7CisJCXJldHVybiBlcnJvcjsKKwl9CisKKwllcnJvciA9IGN5dHRzcDVf ZmlsbF9hbGxfdG91Y2godHMpOworCWlmIChlcnJvciA8IDApIHsKKwkJZGV2X2Vycih0cy0+ZGV2 LCAiRXJyb3Igb24gcmVwb3J0IGRlc2NyaXB0b3Igcj0lZFxuIiwgZXJyb3IpOworCQlyZXR1cm4g ZXJyb3I7CisJfQorCisJZXJyb3IgPSBjeXR0c3A1X2hpZF9vdXRwdXRfZ2V0X3N5c2luZm8odHMp OworCWlmIChlcnJvcikgeworCQlkZXZfZXJyKHRzLT5kZXYsICJFcnJvciBvbiBnZXR0aW5nIHN5 c2luZm8gcj0lZFxuIiwgZXJyb3IpOworCQlyZXR1cm4gZXJyb3I7CisJfQorCisJcmV0dXJuIGVy cm9yOworfQorCisjaWZkZWYgQ09ORklHX09GCitzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2Rldmlj ZV9pZCBjeXR0c3A1X29mX21hdGNoW10gPSB7CisJeyAuY29tcGF0aWJsZSA9ICJjeXByZXNzLHR0 MjEwMDAiLCB9LAorCXsgfQorfTsKK01PRFVMRV9ERVZJQ0VfVEFCTEUob2YsIGN5dHRzcDVfb2Zf bWF0Y2gpOworI2VuZGlmCisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgaTJjX2RldmljZV9pZCBjeXR0 c3A1X2kyY19pZFtdID0geworCXsgQ1lUVFNQNV9OQU1FLCAwLCB9LAorCXsgfQorfTsKK01PRFVM RV9ERVZJQ0VfVEFCTEUoaTJjLCBjeXR0c3A1X2kyY19pZCk7CisKK3N0YXRpYyB2b2lkIGN5dHRz cDVfY2xlYW51cCh2b2lkICpkYXRhKQoreworCXN0cnVjdCBjeXR0c3A1ICp0cyA9IGRhdGE7CisK KwlyZWd1bGF0b3JfZGlzYWJsZSh0cy0+dmRkKTsKK30KKworc3RhdGljIGludCBjeXR0c3A1X3By b2JlKHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IHJlZ21hcCAqcmVnbWFwLCBpbnQgaXJxLAor CQkJIGNvbnN0IGNoYXIgKm5hbWUpCit7CisJc3RydWN0IGN5dHRzcDUgKnRzOworCXN0cnVjdCBj eXR0c3A1X3N5c2luZm8gKnNpOworCWludCBlcnJvciwgaTsKKworCXRzID0gZGV2bV9remFsbG9j KGRldiwgc2l6ZW9mKCp0cyksIEdGUF9LRVJORUwpOworCWlmICghdHMpCisJCXJldHVybiAtRU5P TUVNOworCisJLyogSW5pdGlhbGl6ZSBkZXZpY2UgaW5mbyAqLworCXRzLT5yZWdtYXAgPSByZWdt YXA7CisJdHMtPmRldiA9IGRldjsKKwlzaSA9ICZ0cy0+c3lzaW5mbzsKKwlkZXZfc2V0X2RydmRh dGEoZGV2LCB0cyk7CisKKwlpbml0X2NvbXBsZXRpb24oJnRzLT5jbWRfZG9uZSk7CisKKwkvKiBQ b3dlciB1cCB0aGUgZGV2aWNlICovCisJdHMtPnZkZCA9IGRldm1fcmVndWxhdG9yX2dldChkZXYs ICJ2ZGQiKTsKKwlpZiAoSVNfRVJSKHRzLT52ZGQpKSB7CisJCWVycm9yID0gUFRSX0VSUih0cy0+ dmRkKTsKKwkJZGV2X3NldF9kcnZkYXRhKGRldiwgTlVMTCk7CisJCXJldHVybiBlcnJvcjsKKwl9 CisKKwllcnJvciA9IGRldm1fYWRkX2FjdGlvbl9vcl9yZXNldChkZXYsIGN5dHRzcDVfY2xlYW51 cCwgdHMpOworCWlmIChlcnJvcikgeworCQlkZXZfc2V0X2RydmRhdGEoZGV2LCBOVUxMKTsKKwkJ cmV0dXJuIGVycm9yOworCX0KKworCWVycm9yID0gcmVndWxhdG9yX2VuYWJsZSh0cy0+dmRkKTsK KwlpZiAoZXJyb3IpIHsKKwkJZGV2X3NldF9kcnZkYXRhKGRldiwgTlVMTCk7CisJCXJldHVybiBl cnJvcjsKKwl9CisKKwl0cy0+aW5wdXQgPSBkZXZtX2lucHV0X2FsbG9jYXRlX2RldmljZShkZXYp OworCWlmICghdHMtPmlucHV0KSB7CisJCWRldl9lcnIoZGV2LCAiRXJyb3IsIGZhaWxlZCB0byBh bGxvY2F0ZSBpbnB1dCBkZXZpY2VcbiIpOworCQlyZXR1cm4gLUVOT0RFVjsKKwl9CisKKwl0cy0+ aW5wdXQtPm5hbWUgPSAiY3l0dHNwNSI7CisJc2NucHJpbnRmKHRzLT5waHlzLCBzaXplb2YodHMt PnBoeXMpLCAiJXMvaW5wdXQwIiwgZGV2X25hbWUoZGV2KSk7CisJdHMtPmlucHV0LT5waHlzID0g dHMtPnBoeXM7CisJaW5wdXRfc2V0X2RydmRhdGEodHMtPmlucHV0LCB0cyk7CisKKwkvKiBSZXNl dCB0aGUgZ3BpbyB0byBiZSBpbiBhIHJlc2V0IHN0YXRlICovCisJdHMtPnJlc2V0X2dwaW8gPSBk ZXZtX2dwaW9kX2dldF9vcHRpb25hbChkZXYsICJyZXNldCIsIEdQSU9EX09VVF9ISUdIKTsKKwlp ZiAoSVNfRVJSKHRzLT5yZXNldF9ncGlvKSkgeworCQllcnJvciA9IFBUUl9FUlIodHMtPnJlc2V0 X2dwaW8pOworCQlkZXZfZXJyKGRldiwgIkZhaWxlZCB0byByZXF1ZXN0IHJlc2V0IGdwaW8sIGVy cm9yICVkXG4iLCBlcnJvcik7CisJCXJldHVybiBlcnJvcjsKKwl9CisJZ3Bpb2Rfc2V0X3ZhbHVl KHRzLT5yZXNldF9ncGlvLCAwKTsKKworCS8qIE5lZWQgYSBkZWxheSB0byBoYXZlIGRldmljZSB1 cCAqLworCW1zbGVlcCgyMCk7CisKKwllcnJvciA9IGRldm1fcmVxdWVzdF90aHJlYWRlZF9pcnEo ZGV2LCBpcnEsIE5VTEwsIGN5dHRzcDVfaGFuZGxlX2lycSwKKwkJCQkgICAgICAgSVJRRl9PTkVT SE9ULCBuYW1lLCB0cyk7CisJaWYgKGVycm9yKSB7CisJCWRldl9lcnIoZGV2LCAidW5hYmxlIHRv IHJlcXVlc3QgSVJRXG4iKTsKKwkJcmV0dXJuIGVycm9yOworCX0KKworCWVycm9yID0gY3l0dHNw NV9zdGFydHVwKHRzKTsKKwlpZiAoZXJyb3IpIHsKKwkJZGV2X2Vycih0cy0+ZGV2LCAiRmFpbCBp bml0aWFsIHN0YXJ0dXAgcj0lZFxuIiwgZXJyb3IpOworCQlyZXR1cm4gZXJyb3I7CisJfQorCisJ ZXJyb3IgPSBjeXR0c3A1X3BhcnNlX2R0X2tleV9jb2RlKGRldik7CisJaWYgKGVycm9yIDwgMCkg eworCQlkZXZfZXJyKHRzLT5kZXYsICJFcnJvciB3aGlsZSBwYXJzaW5nIGR0cyAlZFxuIiwgZXJy b3IpOworCQlyZXR1cm4gZXJyb3I7CisJfQorCisJdG91Y2hzY3JlZW5fcGFyc2VfcHJvcGVydGll cyh0cy0+aW5wdXQsIHRydWUsICZ0cy0+cHJvcCk7CisKKwlfX3NldF9iaXQoRVZfS0VZLCB0cy0+ aW5wdXQtPmV2Yml0KTsKKwlmb3IgKGkgPSAwOyBpIDwgc2ktPm51bV9idG5zOyBpKyspCisJCV9f c2V0X2JpdChzaS0+a2V5X2NvZGVbaV0sIHRzLT5pbnB1dC0+a2V5Yml0KTsKKworCXJldHVybiBj eXR0c3A1X3NldHVwX2lucHV0X2RldmljZShkZXYpOworfQorCitzdGF0aWMgaW50IGN5dHRzcDVf aTJjX3Byb2JlKHN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQsCisJCQkgICAgIGNvbnN0IHN0cnVj dCBpMmNfZGV2aWNlX2lkICppZCkKK3sKKwlzdHJ1Y3QgcmVnbWFwICpyZWdtYXA7CisJc3RhdGlj IGNvbnN0IHN0cnVjdCByZWdtYXBfY29uZmlnIGNvbmZpZyA9IHsKKwkJLnJlZ19iaXRzID0gOCwK KwkJLnZhbF9iaXRzID0gOCwKKwl9OworCisJcmVnbWFwID0gZGV2bV9yZWdtYXBfaW5pdF9pMmMo Y2xpZW50LCAmY29uZmlnKTsKKwlpZiAoSVNfRVJSKHJlZ21hcCkpIHsKKwkJZGV2X2VycigmY2xp ZW50LT5kZXYsICJyZWdtYXAgYWxsb2NhdGlvbiBmYWlsZWQ6ICVsZFxuIiwKKwkJCVBUUl9FUlIo cmVnbWFwKSk7CisJCXJldHVybiBQVFJfRVJSKHJlZ21hcCk7CisJfQorCisJcmV0dXJuIGN5dHRz cDVfcHJvYmUoJmNsaWVudC0+ZGV2LCByZWdtYXAsIGNsaWVudC0+aXJxLCBjbGllbnQtPm5hbWUp OworfQorCitzdGF0aWMgc3RydWN0IGkyY19kcml2ZXIgY3l0dHNwNV9pMmNfZHJpdmVyID0gewor CS5kcml2ZXIgPSB7CisJCS5uYW1lID0gQ1lUVFNQNV9OQU1FLAorCQkub2ZfbWF0Y2hfdGFibGUg PSBvZl9tYXRjaF9wdHIoY3l0dHNwNV9vZl9tYXRjaCksCisJfSwKKwkucHJvYmUgPSBjeXR0c3A1 X2kyY19wcm9iZSwKKwkuaWRfdGFibGUgPSBjeXR0c3A1X2kyY19pZCwKK307CisKK21vZHVsZV9p MmNfZHJpdmVyKGN5dHRzcDVfaTJjX2RyaXZlcik7CisKK01PRFVMRV9MSUNFTlNFKCJHUEwiKTsK K01PRFVMRV9ERVNDUklQVElPTigiVG91Y2hzY3JlZW4gZHJpdmVyIGZvciBDeXByZXNzIFRydWVU b3VjaCBHZW4gNSBQcm9kdWN0Iik7CitNT0RVTEVfQVVUSE9SKCJNeWzDqG5lIEpvc3NlcmFuZCA8 bXlsZW5lLmpvc3NlcmFuZEBib290bGluLmNvbT4iKTsKLS0gCjIuMzEuMQoKCl9fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFp bGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlz dHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK