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 42A48C4332F for ; Wed, 23 Mar 2022 12:00:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244042AbiCWMCK (ORCPT ); Wed, 23 Mar 2022 08:02:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235981AbiCWMCH (ORCPT ); Wed, 23 Mar 2022 08:02:07 -0400 Received: from wout2-smtp.messagingengine.com (wout2-smtp.messagingengine.com [64.147.123.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 378A17A99A; Wed, 23 Mar 2022 05:00:37 -0700 (PDT) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.west.internal (Postfix) with ESMTP id D65A33200C14; Wed, 23 Mar 2022 08:00:35 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Wed, 23 Mar 2022 08:00:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alistair23.me; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to; s=fm1; bh=QGAjmaqLEZsGrI vZP2lNR8tobeGnBbdvQYdAeMIPNyA=; b=UlQ1GEZDc3WwgRCFzVOmA++oRG82zc lDXD+OsXzU4rqoln9K6XemTVGeb3E3JvIu0e528mUlbO0vPBzNDP7N+ybeyypeAy OyeLAcHL9pG7RLg9yURsfp2M5yyxjaDQGvGc2G0jHEUeqxtS688jmGxgyVYJIKYn +IdKddGXG3WrhnDmR7CVoNtlAP6h7CfoB9mLh8U2eF6FqhUPann+9DUyPl+iBgTC PSpp9p3tnr31eQtZ57W1ReFKTZBZi5oGg7ZsxuDQ88Abkl7GB2ac4Xam1c9C+UBt Iak8L/xewscnmAOW5kTU+er0VdWf1WTJVBtFopyvB97eHkAfWuUwbwpg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; bh=QGAjmaqLEZsGrIvZP2lNR8tobeGnBbdvQYdAeMIPN yA=; b=hYtP2ytrRE0g8g4Jn2B633wYQDgNTZOeYDhjVXbGEQPYZEShWNouJMx7e Lp1i0l834+A/9Mu8NcN0LbwNigpE3S8ebQkcWEm9lzggvZ71/F1s2KDC618I/QEm 1rg4slCbjhakn4DjsDG3ZJsfWJbm97CRURp8W+G3UPUf+94iWoIuQ/9qpmT0CgqY OvxMlidHR1mhJhpu/0nZtuPGcf8sKpjJyOx7O5IwiVux6C+TaNI/XU0hw3DZUB7O XqIxRE7UOiRs6rTiXfwm9vWD60uPLNeX34Fodf87zZqfeLwyJ0BMyEUKojzbXIcs z6dpxZWmo/TZS23eIzzpX/DFVkjng== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvvddrudegjedgfeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfgggtgfesthekredtredtjeenucfhrhhomheptehlihhs thgrihhrucfhrhgrnhgtihhsuceorghlihhsthgrihhrsegrlhhishhtrghirhdvfedrmh gvqeenucggtffrrghtthgvrhhnpeejfeethfefudefgeffkefgueffgeefteefgfffheeg lefgvddvheevtdeuueejjeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmh grihhlfhhrohhmpegrlhhishhtrghirhesrghlihhsthgrihhrvdefrdhmvg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 23 Mar 2022 08:00:30 -0400 (EDT) From: Alistair Francis To: linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: alistair23@gmail.com, rydberg@bitmath.org, linus.walleij@linaro.org, robh+dt@kernel.org, dmitry.torokhov@gmail.com, andreas@kemnade.info, Alistair Francis , Maxime Ripard , =?UTF-8?q?Myl=C3=A8ne=20Josserand?= , Peter Geis Subject: [PATCH v7 1/4] Input: Add driver for Cypress Generation 5 touchscreen Date: Wed, 23 Mar 2022 22:00:18 +1000 Message-Id: <20220323120021.361137-2-alistair@alistair23.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220323120021.361137-1-alistair@alistair23.me> References: <20220323120021.361137-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 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 Tested-by: Andreas Kemnade # Kobo Clara HD Tested-by: Peter Geis --- drivers/input/touchscreen/Kconfig | 16 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/cyttsp5.c | 902 ++++++++++++++++++++++++++++ 3 files changed, 919 insertions(+) create mode 100644 drivers/input/touchscreen/cyttsp5.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 2f6adfb7b938..eb4e1b156683 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -284,6 +284,22 @@ 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 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..3ac45108090c --- /dev/null +++ b/drivers/input/touchscreen/cyttsp5.c @@ -0,0 +1,902 @@ +// 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 + +#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 GENMASK(CY_BITS_PER_BTN, 0) + +#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 GENMASK(6, 0) + +#define HID_SYSINFO_SENSING_OFFSET 33 +#define HID_SYSINFO_BTN_OFFSET 48 +#define HID_SYSINFO_BTN_MASK GENMASK(7, 0) +#define HID_SYSINFO_MAX_BTN 8 + +#define CY_HID_OUTPUT_TIMEOUT_MS 200 +#define CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT_MS 3000 +#define CY_HID_GET_HID_DESCRIPTOR_TIMEOUT_MS 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 + +/* 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 is understood in the datasheet, the register does not + * matter. For consistency, use 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] = (reg >> 8) & 0xFF ; + + /* Copy the rest of the data */ + if (data) + memcpy(&cmd[1], data, size); + + /* + * The hardware wants to receive a frame with the address register + * contained 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, reg & 0xFF, 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 += ((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; + + if (!si->num_btns) + return 0; + + /* Initialize the button to RESERVED */ + memset32(si->key_code, KEY_RESERVED, si->num_btns); + + 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 (get_unaligned_le16(&ts->response_buf[size - 3]) != 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 */ + put_unaligned_le16(HID_OUTPUT_GET_SYSINFO_SIZE, cmd); + 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_MS)); + if (rc <= 0) { + dev_err(ts->dev, "HID output cmd execution timed out\n"); + rc = -ETIMEDOUT; + 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; + + put_unaligned_le16(HID_OUTPUT_BL_LAUNCH_APP_SIZE, cmd); + cmd[2] = HID_BL_OUTPUT_REPORT_ID; + cmd[3] = 0x0; /* Reserved */ + cmd[4] = HID_OUTPUT_BL_SOP; + cmd[5] = HID_OUTPUT_BL_LAUNCH_APP; + put_unaligned_le16(0x00, &cmd[6]); + crc = crc_itu_t(0xFFFF, &cmd[4], 4); + put_unaligned_le16(crc, &cmd[8]); + 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_MS)); + if (rc <= 0) { + dev_err(ts->dev, "HID output cmd execution timed out\n"); + rc = -ETIMEDOUT; + 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_MS)); + if (rc <= 0) { + dev_err(ts->dev, "HID get descriptor timed out\n"); + rc = -ETIMEDOUT; + return rc; + } + + memcpy(desc, ts->response_buf, sizeof(*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, sizeof(buf)); + 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; +} + +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); + return error; + } + + error = devm_add_action_or_reset(dev, cyttsp5_cleanup, ts); + if (error) { + return error; + } + + error = regulator_enable(ts->vdd); + if (error) { + 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 const struct of_device_id cyttsp5_of_match[] = { + { .compatible = "cypress,tt21000", }, + { } +}; +MODULE_DEVICE_TABLE(of, cyttsp5_of_match); + +static const struct i2c_device_id cyttsp5_i2c_id[] = { + { CYTTSP5_NAME, 0, }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id); + +static struct i2c_driver cyttsp5_i2c_driver = { + .driver = { + .name = CYTTSP5_NAME, + .of_match_table = 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.35.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 12057C433EF for ; Wed, 23 Mar 2022 12:02:09 +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=l9fXt+lP1wbuPliphpz3S0xR5MI0AzzcZ1Qccbu0SNY=; b=iUrwkW6sejamq3 dDCn7TAjSJFw6Eh1bNrK/ELTrB6JG7wfRQGuIac9QpiDIgbh5VXuI8H2T5i/VZu1xWFbP3VFiIPHO zjiGlBw7kT205HeMqxJxK5raGnTRXcrNgZjoTaS4y/Ea/ijUQv3PA7uIZb9n0ptt++nmCQ3jz0PiF t6RgEvGkyXTg58oDB/fALYi17qTNTvgdmTqMIMaooQznSrD0wmAhUIiHadolgVNP6XpKLv6CZFnAL qy+i6xhmYUAINcvnOseI5i4zG6iSf0O1k5qpj47nDI29XayR8WVnStGQ05i1XUgzaA2H7++/AbKp1 3spStyQDJ+kprb/QtOaA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nWzfR-00DXKh-9J; Wed, 23 Mar 2022 12:00:45 +0000 Received: from wout2-smtp.messagingengine.com ([64.147.123.25]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nWzfJ-00DXIE-7p for linux-arm-kernel@lists.infradead.org; Wed, 23 Mar 2022 12:00:40 +0000 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.west.internal (Postfix) with ESMTP id D65A33200C14; Wed, 23 Mar 2022 08:00:35 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Wed, 23 Mar 2022 08:00:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alistair23.me; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to; s=fm1; bh=QGAjmaqLEZsGrI vZP2lNR8tobeGnBbdvQYdAeMIPNyA=; b=UlQ1GEZDc3WwgRCFzVOmA++oRG82zc lDXD+OsXzU4rqoln9K6XemTVGeb3E3JvIu0e528mUlbO0vPBzNDP7N+ybeyypeAy OyeLAcHL9pG7RLg9yURsfp2M5yyxjaDQGvGc2G0jHEUeqxtS688jmGxgyVYJIKYn +IdKddGXG3WrhnDmR7CVoNtlAP6h7CfoB9mLh8U2eF6FqhUPann+9DUyPl+iBgTC PSpp9p3tnr31eQtZ57W1ReFKTZBZi5oGg7ZsxuDQ88Abkl7GB2ac4Xam1c9C+UBt Iak8L/xewscnmAOW5kTU+er0VdWf1WTJVBtFopyvB97eHkAfWuUwbwpg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; bh=QGAjmaqLEZsGrIvZP2lNR8tobeGnBbdvQYdAeMIPN yA=; b=hYtP2ytrRE0g8g4Jn2B633wYQDgNTZOeYDhjVXbGEQPYZEShWNouJMx7e Lp1i0l834+A/9Mu8NcN0LbwNigpE3S8ebQkcWEm9lzggvZ71/F1s2KDC618I/QEm 1rg4slCbjhakn4DjsDG3ZJsfWJbm97CRURp8W+G3UPUf+94iWoIuQ/9qpmT0CgqY OvxMlidHR1mhJhpu/0nZtuPGcf8sKpjJyOx7O5IwiVux6C+TaNI/XU0hw3DZUB7O XqIxRE7UOiRs6rTiXfwm9vWD60uPLNeX34Fodf87zZqfeLwyJ0BMyEUKojzbXIcs z6dpxZWmo/TZS23eIzzpX/DFVkjng== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvvddrudegjedgfeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfgggtgfesthekredtredtjeenucfhrhhomheptehlihhs thgrihhrucfhrhgrnhgtihhsuceorghlihhsthgrihhrsegrlhhishhtrghirhdvfedrmh gvqeenucggtffrrghtthgvrhhnpeejfeethfefudefgeffkefgueffgeefteefgfffheeg lefgvddvheevtdeuueejjeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmh grihhlfhhrohhmpegrlhhishhtrghirhesrghlihhsthgrihhrvdefrdhmvg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 23 Mar 2022 08:00:30 -0400 (EDT) From: Alistair Francis To: linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: alistair23@gmail.com, rydberg@bitmath.org, linus.walleij@linaro.org, robh+dt@kernel.org, dmitry.torokhov@gmail.com, andreas@kemnade.info, Alistair Francis , Maxime Ripard , =?UTF-8?q?Myl=C3=A8ne=20Josserand?= , Peter Geis Subject: [PATCH v7 1/4] Input: Add driver for Cypress Generation 5 touchscreen Date: Wed, 23 Mar 2022 22:00:18 +1000 Message-Id: <20220323120021.361137-2-alistair@alistair23.me> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220323120021.361137-1-alistair@alistair23.me> References: <20220323120021.361137-1-alistair@alistair23.me> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220323_050037_383666_D61DD35A X-CRM114-Status: GOOD ( 27.50 ) 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 VGhpcyBpcyB0aGUgYmFzaWMgZHJpdmVyIGZvciB0aGUgQ3lwcmVzcyBUcnVlVG91Y2ggR2VuNSB0 b3VjaHNjcmVlbgpjb250cm9sbGVycy4gVGhpcyBkcml2ZXIgc3VwcG9ydHMgb25seSB0aGUgSTJD IGJ1cyBidXQgaXQgdXNlcyByZWdtYXAKc28gU1BJIHN1cHBvcnQgY291bGQgYmUgYWRkZWQgbGF0 ZXIuClRoZSB0b3VjaHNjcmVlbiBjYW4gcmV0cmlldmUgc29tZSBkZWZpbmVkIHpvbmUgdGhhdCBh cmUgaGFuZGxlZCBhcwpidXR0b25zIChhY2NvcmRpbmcgdG8gdGhlIGhhcmR3YXJlKS4gVGhhdCBp cyB3aHkgaXQgaGFuZGxlcwpidXR0b24gYW5kIG11bHRpdG91Y2ggZXZlbnRzLgoKUmV2aWV3ZWQt Ynk6IE1heGltZSBSaXBhcmQgPG1heGltZS5yaXBhcmRAYm9vdGxpbi5jb20+ClNpZ25lZC1vZmYt Ynk6IE15bMOobmUgSm9zc2VyYW5kIDxteWxlbmUuam9zc2VyYW5kQGJvb3RsaW4uY29tPgpTaWdu ZWQtb2ZmLWJ5OiBBbGlzdGFpciBGcmFuY2lzIDxhbGlzdGFpckBhbGlzdGFpcjIzLm1lPgpUZXN0 ZWQtYnk6IEFuZHJlYXMgS2VtbmFkZSA8YW5kcmVhc0BrZW1uYWRlLmluZm8+ICMgS29ibyBDbGFy YSBIRApUZXN0ZWQtYnk6IFBldGVyIEdlaXMgPHBnd2lwZW91dEBnbWFpbC5jb20+Ci0tLQogZHJp dmVycy9pbnB1dC90b3VjaHNjcmVlbi9LY29uZmlnICAgfCAgMTYgKwogZHJpdmVycy9pbnB1dC90 b3VjaHNjcmVlbi9NYWtlZmlsZSAgfCAgIDEgKwogZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9j eXR0c3A1LmMgfCA5MDIgKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogMyBmaWxlcyBjaGFu Z2VkLCA5MTkgaW5zZXJ0aW9ucygrKQogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaW5wdXQv dG91Y2hzY3JlZW4vY3l0dHNwNS5jCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9pbnB1dC90b3VjaHNj cmVlbi9LY29uZmlnIGIvZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9LY29uZmlnCmluZGV4IDJm NmFkZmI3YjkzOC4uZWI0ZTFiMTU2NjgzIDEwMDY0NAotLS0gYS9kcml2ZXJzL2lucHV0L3RvdWNo c2NyZWVuL0tjb25maWcKKysrIGIvZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9LY29uZmlnCkBA IC0yODQsNiArMjg0LDIyIEBAIGNvbmZpZyBUT1VDSFNDUkVFTl9DWVRUU1A0X1NQSQogCSAgVG8g Y29tcGlsZSB0aGlzIGRyaXZlciBhcyBhIG1vZHVsZSwgY2hvb3NlIE0gaGVyZTogdGhlCiAJICBt b2R1bGUgd2lsbCBiZSBjYWxsZWQgY3l0dHNwNF9zcGkuCiAKK2NvbmZpZyBUT1VDSFNDUkVFTl9D WVRUU1A1CisJdHJpc3RhdGUgIkN5cHJlc3MgVHJ1ZVRvdWNoIEdlbjUgVG91Y2hzY3JlZW4gRHJp dmVyIgorCWRlcGVuZHMgb24gSTJDCisJc2VsZWN0IFJFR01BUF9JMkMKKwlzZWxlY3QgQ1JDX0lU VV9UCisJaGVscAorCSAgRHJpdmVyIGZvciBQYXJhZGUgVHJ1ZVRvdWNoIFN0YW5kYXJkIFByb2R1 Y3QgR2VuZXJhdGlvbiA1CisJICB0b3VjaHNjcmVlbiBjb250cm9sbGVycy4gSTJDIGJ1cyBpbnRl cmZhY2Ugc3VwcG9ydCBvbmx5LgorCisJICBTYXkgWSBoZXJlIGlmIHlvdSBoYXZlIGEgQ3lwcmVz cyBHZW41IHRvdWNoc2NyZWVuLgorCisJICBJZiB1bnN1cmUsIHNheSBOLgorCisJICBUbyBjb21w aWxlIHRoaXMgZHJpdmVyIGFzIGEgbW9kdWxlLCBjaG9vc2UgTSBoZXJlOiB0aGUKKwkgIG1vZHVs ZSB3aWxsIGJlIGNhbGxlZCBjeXR0c3A1LgorCiBjb25maWcgVE9VQ0hTQ1JFRU5fREE5MDM0CiAJ dHJpc3RhdGUgIlRvdWNoc2NyZWVuIHN1cHBvcnQgZm9yIERpYWxvZyBTZW1pY29uZHVjdG9yIERB OTAzNCIKIAlkZXBlbmRzIG9uIFBNSUNfREE5MDNYCmRpZmYgLS1naXQgYS9kcml2ZXJzL2lucHV0 L3RvdWNoc2NyZWVuL01ha2VmaWxlIGIvZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9NYWtlZmls ZQppbmRleCAzOWE4MTI3Y2Y2YTUuLjBlYTVjNDdmN2ZkOSAxMDA2NDQKLS0tIGEvZHJpdmVycy9p bnB1dC90b3VjaHNjcmVlbi9NYWtlZmlsZQorKysgYi9kcml2ZXJzL2lucHV0L3RvdWNoc2NyZWVu L01ha2VmaWxlCkBAIC0zMCw2ICszMCw3IEBAIG9iai0kKENPTkZJR19UT1VDSFNDUkVFTl9DWVRU U1BfU1BJKQkrPSBjeXR0c3Bfc3BpLm8KIG9iai0kKENPTkZJR19UT1VDSFNDUkVFTl9DWVRUU1A0 X0NPUkUpCSs9IGN5dHRzcDRfY29yZS5vCiBvYmotJChDT05GSUdfVE9VQ0hTQ1JFRU5fQ1lUVFNQ NF9JMkMpCSs9IGN5dHRzcDRfaTJjLm8gY3l0dHNwX2kyY19jb21tb24ubwogb2JqLSQoQ09ORklH X1RPVUNIU0NSRUVOX0NZVFRTUDRfU1BJKQkrPSBjeXR0c3A0X3NwaS5vCitvYmotJChDT05GSUdf VE9VQ0hTQ1JFRU5fQ1lUVFNQNSkJKz0gY3l0dHNwNS5vCiBvYmotJChDT05GSUdfVE9VQ0hTQ1JF RU5fREE5MDM0KQkrPSBkYTkwMzQtdHMubwogb2JqLSQoQ09ORklHX1RPVUNIU0NSRUVOX0RBOTA1 MikJKz0gZGE5MDUyX3RzaS5vCiBvYmotJChDT05GSUdfVE9VQ0hTQ1JFRU5fRFlOQVBSTykJKz0g ZHluYXByby5vCmRpZmYgLS1naXQgYS9kcml2ZXJzL2lucHV0L3RvdWNoc2NyZWVuL2N5dHRzcDUu YyBiL2RyaXZlcnMvaW5wdXQvdG91Y2hzY3JlZW4vY3l0dHNwNS5jCm5ldyBmaWxlIG1vZGUgMTAw NjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uM2FjNDUxMDgwOTBjCi0tLSAvZGV2L251bGwKKysrIGIv ZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9jeXR0c3A1LmMKQEAgLTAsMCArMSw5MDIgQEAKKy8v IFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wCisvKgorICogUGFyYWRlIFRydWVUb3Vj aChUTSkgU3RhbmRhcmQgUHJvZHVjdCBWNSBNb2R1bGUuCisgKgorICogQ29weXJpZ2h0IChDKSAy MDE1IFBhcmFkZSBUZWNobm9sb2dpZXMKKyAqIENvcHlyaWdodCAoQykgMjAxMi0yMDE1IEN5cHJl c3MgU2VtaWNvbmR1Y3RvcgorICogQ29weXJpZ2h0IChDKSAyMDE4IEJvb3RsaW4KKyAqCisgKiBB dXRob3JzOiBNeWzDqG5lIEpvc3NlcmFuZCA8bXlsZW5lLmpvc3NlcmFuZEBib290bGluLmNvbT4K KyAqICAgICAgICAgICAgICAgIEFsaXN0YWlyIEZyYW5jaXMgPGFsaXN0YWlyQGFsaXN0YWlyMjMu bWU+CisgKi8KKworI2luY2x1ZGUgPGxpbnV4L2NyYy1pdHUtdC5oPgorI2luY2x1ZGUgPGxpbnV4 L2RlbGF5Lmg+CisjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+CisjaW5jbHVkZSA8bGludXgvZ3Bp by9jb25zdW1lci5oPgorI2luY2x1ZGUgPGxpbnV4L2lucHV0L210Lmg+CisjaW5jbHVkZSA8bGlu dXgvaW5wdXQvdG91Y2hzY3JlZW4uaD4KKyNpbmNsdWRlIDxsaW51eC9pbnRlcnJ1cHQuaD4KKyNp bmNsdWRlIDxsaW51eC9pMmMuaD4KKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRl IDxsaW51eC9vZl9kZXZpY2UuaD4KKyNpbmNsdWRlIDxsaW51eC9yZWdtYXAuaD4KKyNpbmNsdWRl IDxhc20vdW5hbGlnbmVkLmg+CisKKyNkZWZpbmUgQ1lUVFNQNV9OQU1FCQkJCSJjeXR0c3A1Igor I2RlZmluZSBDWV9JMkNfREFUQV9TSVpFCQkJKDIgKiAyNTYpCisjZGVmaW5lIEhJRF9WRVJTSU9O CQkJCTB4MDEwMAorI2RlZmluZSBDWV9NQVhfSU5QVVQJCQkJNTEyCisjZGVmaW5lIENZVFRTUDVf UFJFQUxMT0NBVEVEX0NNRF9CVUZGRVIJMzIKKyNkZWZpbmUgQ1lfQklUU19QRVJfQlROCQkJMQor I2RlZmluZSBDWV9OVU1fQlROX0VWRU5UX0lECQkJR0VOTUFTSyhDWV9CSVRTX1BFUl9CVE4sIDAp CisKKyNkZWZpbmUgTUFYX0FSRUEJCQkJMjU1CisjZGVmaW5lIEhJRF9PVVRQVVRfQkxfU09QCQkJ MHgxCisjZGVmaW5lIEhJRF9PVVRQVVRfQkxfRU9QCQkJMHgxNworI2RlZmluZSBISURfT1VUUFVU X0JMX0xBVU5DSF9BUFAJCTB4M0IKKyNkZWZpbmUgSElEX09VVFBVVF9CTF9MQVVOQ0hfQVBQX1NJ WkUJCTExCisjZGVmaW5lIEhJRF9PVVRQVVRfR0VUX1NZU0lORk8JCQkweDIKKyNkZWZpbmUgSElE X09VVFBVVF9HRVRfU1lTSU5GT19TSVpFCQk1CisjZGVmaW5lIEhJRF9PVVRQVVRfTUFYX0NNRF9T SVpFCQkxMgorCisjZGVmaW5lIEhJRF9ERVNDX1JFRwkJCQkweDEKKyNkZWZpbmUgSElEX0lOUFVU X1JFRwkJCQkweDMKKyNkZWZpbmUgSElEX09VVFBVVF9SRUcJCQkJMHg0CisKKyNkZWZpbmUgUkVQ T1JUX0lEX1RPVUNICQkJMHgxCisjZGVmaW5lIFJFUE9SVF9JRF9CVE4JCQkJMHgzCisjZGVmaW5l IFJFUE9SVF9TSVpFXzUJCQkJNQorI2RlZmluZSBSRVBPUlRfU0laRV84CQkJCTgKKyNkZWZpbmUg UkVQT1JUX1NJWkVfMTYJCQkJMTYKKworLyogVG91Y2ggcmVwb3J0cyBvZmZzZXRzICovCisvKiBI ZWFkZXIgb2Zmc2V0cyAqLworI2RlZmluZSBUT1VDSF9SRVBPUlRfREVTQ19IRFJfQ09OVEFDVENP VU5UCTE2CisvKiBSZWNvcmQgb2Zmc2V0cyAqLworI2RlZmluZSBUT1VDSF9SRVBPUlRfREVTQ19D T05UQUNUSUQJCTgKKyNkZWZpbmUgVE9VQ0hfUkVQT1JUX0RFU0NfWAkJCTE2CisjZGVmaW5lIFRP VUNIX1JFUE9SVF9ERVNDX1kJCQkzMgorI2RlZmluZSBUT1VDSF9SRVBPUlRfREVTQ19QCQkJNDgK KyNkZWZpbmUgVE9VQ0hfUkVQT1JUX0RFU0NfTUFKCQkJNTYKKyNkZWZpbmUgVE9VQ0hfUkVQT1JU X0RFU0NfTUlOCQkJNjQKKworLyogSElEICovCisjZGVmaW5lIEhJRF9UT1VDSF9SRVBPUlRfSUQJ CQkweDEKKyNkZWZpbmUgSElEX0JUTl9SRVBPUlRfSUQJCQkweDMKKyNkZWZpbmUgSElEX0FQUF9S RVNQT05TRV9SRVBPUlRfSUQJCTB4MUYKKyNkZWZpbmUgSElEX0FQUF9PVVRQVVRfUkVQT1JUX0lE CQkweDJGCisjZGVmaW5lIEhJRF9CTF9SRVNQT05TRV9SRVBPUlRfSUQJCTB4MzAKKyNkZWZpbmUg SElEX0JMX09VVFBVVF9SRVBPUlRfSUQJCTB4NDAKKworI2RlZmluZSBISURfT1VUUFVUX1JFU1BP TlNFX1JFUE9SVF9PRkZTRVQJMgorI2RlZmluZSBISURfT1VUUFVUX1JFU1BPTlNFX0NNRF9PRkZT RVQJCTQKKyNkZWZpbmUgSElEX09VVFBVVF9SRVNQT05TRV9DTURfTUFTSwkJR0VOTUFTSyg2LCAw KQorCisjZGVmaW5lIEhJRF9TWVNJTkZPX1NFTlNJTkdfT0ZGU0VUCQkzMworI2RlZmluZSBISURf U1lTSU5GT19CVE5fT0ZGU0VUCQkJNDgKKyNkZWZpbmUgSElEX1NZU0lORk9fQlROX01BU0sJCQlH RU5NQVNLKDcsIDApCisjZGVmaW5lIEhJRF9TWVNJTkZPX01BWF9CVE4JCQk4CisKKyNkZWZpbmUg Q1lfSElEX09VVFBVVF9USU1FT1VUX01TCQkJMjAwCisjZGVmaW5lIENZX0hJRF9PVVRQVVRfR0VU X1NZU0lORk9fVElNRU9VVF9NUwkzMDAwCisjZGVmaW5lIENZX0hJRF9HRVRfSElEX0RFU0NSSVBU T1JfVElNRU9VVF9NUwk0MDAwCisKKy8qIG1heGltdW0gbnVtYmVyIG9mIGNvbmN1cnJlbnQgdHJh Y2tzICovCisjZGVmaW5lIFRPVUNIX1JFUE9SVF9TSVpFCQkJMTAKKyNkZWZpbmUgVE9VQ0hfSU5Q VVRfSEVBREVSX1NJWkUJCTcKKyNkZWZpbmUgQlROX1JFUE9SVF9TSVpFCQkJOQorI2RlZmluZSBC VE5fSU5QVVRfSEVBREVSX1NJWkUJCQk1CisKKyNkZWZpbmUgTUFYX0NZX1RDSF9UX0lEUwkzMgor CisvKiBBbGwgdXNhZ2UgcGFnZXMgZm9yIFRvdWNoIFJlcG9ydCAqLworI2RlZmluZSBUT1VDSF9S RVBPUlRfVVNBR0VfUEdfWAkJMHgwMDAxMDAzMAorI2RlZmluZSBUT1VDSF9SRVBPUlRfVVNBR0Vf UEdfWQkJMHgwMDAxMDAzMQorI2RlZmluZSBUT1VDSF9SRVBPUlRfVVNBR0VfUEdfUAkJMHgwMDBE MDAzMAorI2RlZmluZSBUT1VDSF9SRVBPUlRfVVNBR0VfUEdfQ09OVEFDVElECTB4MDAwRDAwNTEK KyNkZWZpbmUgVE9VQ0hfUkVQT1JUX1VTQUdFX1BHX0NPTlRBQ1RDT1VOVAkweDAwMEQwMDU0Cisj ZGVmaW5lIFRPVUNIX1JFUE9SVF9VU0FHRV9QR19NQUoJCTB4RkYwMTAwNjIKKyNkZWZpbmUgVE9V Q0hfUkVQT1JUX1VTQUdFX1BHX01JTgkJMHhGRjAxMDA2MworI2RlZmluZSBUT1VDSF9DT0xfVVNB R0VfUEcJCQkweDAwMEQwMDIyCisKKy8qIFN5c3RlbSBJbmZvcm1hdGlvbiBpbnRlcmZhY2UgZGVm aW5pdGlvbnMgKi8KK3N0cnVjdCBjeXR0c3A1X3NlbnNpbmdfY29uZl9kYXRhX2RldiB7CisJdTgg ZWxlY3Ryb2Rlc194OworCXU4IGVsZWN0cm9kZXNfeTsKKwlfX2xlMTYgbGVuX3g7CisJX19sZTE2 IGxlbl95OworCV9fbGUxNiByZXNfeDsKKwlfX2xlMTYgcmVzX3k7CisJX19sZTE2IG1heF96Owor CXU4IG9yaWdpbl94OworCXU4IG9yaWdpbl95OworCXU4IGJ0bjsKKwl1OCBzY2FuX21vZGU7CisJ dTggbWF4X251bV9vZl90Y2hfcGVyX3JlZnJlc2hfY3ljbGU7Cit9IF9fcGFja2VkOworCitzdHJ1 Y3QgY3l0dHNwNV9zZW5zaW5nX2NvbmZfZGF0YSB7CisJdTE2IHJlc194OworCXUxNiByZXNfeTsK Kwl1MTYgbWF4X3o7CisJdTE2IGxlbl94OworCXUxNiBsZW5feTsKKwl1OCBvcmlnaW5feDsKKwl1 OCBvcmlnaW5feTsKKwl1OCBtYXhfdGNoOworfTsKKworZW51bSBjeXR0c3A1X3RjaF9hYnMgewkv KiBmb3Igb3JkZXJpbmcgd2l0aGluIHRoZSBleHRyYWN0ZWQgdG91Y2ggZGF0YSBhcnJheSAqLwor CUNZX1RDSF9YLAkvKiBYICovCisJQ1lfVENIX1ksCS8qIFkgKi8KKwlDWV9UQ0hfUCwJLyogUCAo WikgKi8KKwlDWV9UQ0hfVCwJLyogVE9VQ0ggSUQgKi8KKwlDWV9UQ0hfTUFKLAkvKiBUT1VDSF9N QUpPUiAqLworCUNZX1RDSF9NSU4sCS8qIFRPVUNIX01JTk9SICovCisJQ1lfVENIX05VTV9BQlMK K307CisKK3N0cnVjdCBjeXR0c3A1X3RjaF9hYnNfcGFyYW1zIHsKKwlzaXplX3Qgb2ZzOwkvKiBh YnMgYnl0ZSBvZmZzZXQgKi8KKwlzaXplX3Qgc2l6ZTsJLyogc2l6ZSBpbiBiaXRzICovCisJc2l6 ZV90IG1pbjsJLyogbWluIHZhbHVlICovCisJc2l6ZV90IG1heDsJLyogbWF4IHZhbHVlICovCisJ c2l6ZV90IGJvZnM7CS8qIGJpdCBvZmZzZXQgKi8KK307CisKK3N0cnVjdCBjeXR0c3A1X3RvdWNo IHsKKwlpbnQgYWJzW0NZX1RDSF9OVU1fQUJTXTsKK307CisKK3N0cnVjdCBjeXR0c3A1X3N5c2lu Zm8geworCXN0cnVjdCBjeXR0c3A1X3NlbnNpbmdfY29uZl9kYXRhIHNlbnNpbmdfY29uZl9kYXRh OworCWludCBudW1fYnRuczsKKwlzdHJ1Y3QgY3l0dHNwNV90Y2hfYWJzX3BhcmFtcyB0Y2hfaGRy OworCXN0cnVjdCBjeXR0c3A1X3RjaF9hYnNfcGFyYW1zIHRjaF9hYnNbQ1lfVENIX05VTV9BQlNd OworCXUzMiBrZXlfY29kZVtISURfU1lTSU5GT19NQVhfQlROXTsKK307CisKK3N0cnVjdCBjeXR0 c3A1X2hpZF9kZXNjIHsKKwlfX2xlMTYgaGlkX2Rlc2NfbGVuOworCXU4IHBhY2tldF9pZDsKKwl1 OCByZXNlcnZlZF9ieXRlOworCV9fbGUxNiBiY2RfdmVyc2lvbjsKKwlfX2xlMTYgcmVwb3J0X2Rl c2NfbGVuOworCV9fbGUxNiByZXBvcnRfZGVzY19yZWdpc3RlcjsKKwlfX2xlMTYgaW5wdXRfcmVn aXN0ZXI7CisJX19sZTE2IG1heF9pbnB1dF9sZW47CisJX19sZTE2IG91dHB1dF9yZWdpc3RlcjsK KwlfX2xlMTYgbWF4X291dHB1dF9sZW47CisJX19sZTE2IGNvbW1hbmRfcmVnaXN0ZXI7CisJX19s ZTE2IGRhdGFfcmVnaXN0ZXI7CisJX19sZTE2IHZlbmRvcl9pZDsKKwlfX2xlMTYgcHJvZHVjdF9p ZDsKKwlfX2xlMTYgdmVyc2lvbl9pZDsKKwl1OCByZXNlcnZlZFs0XTsKK30gX19wYWNrZWQ7CisK K3N0cnVjdCBjeXR0c3A1IHsKKwlzdHJ1Y3QgZGV2aWNlICpkZXY7CisJc3RydWN0IGNvbXBsZXRp b24gY21kX2RvbmU7CisJc3RydWN0IGN5dHRzcDVfc3lzaW5mbyBzeXNpbmZvOworCXN0cnVjdCBj eXR0c3A1X2hpZF9kZXNjIGhpZF9kZXNjOworCXU4IGNtZF9idWZbQ1lUVFNQNV9QUkVBTExPQ0FU RURfQ01EX0JVRkZFUl07CisJdTggaW5wdXRfYnVmW0NZX01BWF9JTlBVVF07CisJdTggcmVzcG9u c2VfYnVmW0NZX01BWF9JTlBVVF07CisJc3RydWN0IGdwaW9fZGVzYyAqcmVzZXRfZ3BpbzsKKwlz dHJ1Y3QgaW5wdXRfZGV2ICppbnB1dDsKKwljaGFyIHBoeXNbTkFNRV9NQVhdOworCWludCBudW1f cHJ2X3JlYzsKKwlzdHJ1Y3QgcmVnbWFwICpyZWdtYXA7CisJc3RydWN0IHRvdWNoc2NyZWVuX3By b3BlcnRpZXMgcHJvcDsKKwlzdHJ1Y3QgcmVndWxhdG9yICp2ZGQ7Cit9OworCisvKgorICogRm9y IHdoYXQgaXMgdW5kZXJzdG9vZCBpbiB0aGUgZGF0YXNoZWV0LCB0aGUgcmVnaXN0ZXIgZG9lcyBu b3QKKyAqIG1hdHRlci4gRm9yIGNvbnNpc3RlbmN5LCB1c2UgdGhlIElucHV0IFJlZ2lzdGVyIGFk ZHJlc3MKKyAqIGJ1dCBpdCBkb2VzIG1lYW4gYW55dGhpbmcgdG8gdGhlIGRldmljZS4gVGhlIGlt cG9ydGFudCBkYXRhCisgKiB0byBzZW5kIGlzIHRoZSBJMkMgYWRkcmVzcworICovCitzdGF0aWMg aW50IGN5dHRzcDVfcmVhZChzdHJ1Y3QgY3l0dHNwNSAqdHMsIHU4ICpidWYsIHUzMiBtYXgpCit7 CisJaW50IGVycm9yOworCXUzMiBzaXplOworCXU4IHRlbXBbMl07CisKKwkvKiBSZWFkIHRoZSBm cmFtZSB0byByZXRyaWV2ZSB0aGUgc2l6ZSAqLworCWVycm9yID0gcmVnbWFwX2J1bGtfcmVhZCh0 cy0+cmVnbWFwLCBISURfSU5QVVRfUkVHLCB0ZW1wLCBzaXplb2YodGVtcCkpOworCWlmIChlcnJv cikKKwkJcmV0dXJuIGVycm9yOworCisJc2l6ZSA9IGdldF91bmFsaWduZWRfbGUxNih0ZW1wKTsK KwlpZiAoIXNpemUgfHwgc2l6ZSA9PSAyKQorCQlyZXR1cm4gMDsKKworCWlmIChzaXplID4gbWF4 KQorCQlyZXR1cm4gLUVJTlZBTDsKKworCS8qIEdldCB0aGUgcmVhbCB2YWx1ZSAqLworCXJldHVy biByZWdtYXBfYnVsa19yZWFkKHRzLT5yZWdtYXAsIEhJRF9JTlBVVF9SRUcsIGJ1Ziwgc2l6ZSk7 Cit9CisKK3N0YXRpYyBpbnQgY3l0dHNwNV93cml0ZShzdHJ1Y3QgY3l0dHNwNSAqdHMsIHVuc2ln bmVkIGludCByZWcsIHU4ICpkYXRhLAorCQkJIHNpemVfdCBzaXplKQoreworCXU4IGNtZFtISURf T1VUUFVUX01BWF9DTURfU0laRV07CisKKwlpZiAoc2l6ZSArIDEgPiBISURfT1VUUFVUX01BWF9D TURfU0laRSkKKwkJcmV0dXJuIC1FMkJJRzsKKworCS8qIEhpZ2ggYnl0ZXMgb2YgcmVnaXN0ZXIg YWRkcmVzcyBuZWVkZWQgYXMgZmlyc3QgYnl0ZSBvZiBjbWQgKi8KKwljbWRbMF0gPSAocmVnID4+ IDgpICYgMHhGRiA7CisKKwkvKiBDb3B5IHRoZSByZXN0IG9mIHRoZSBkYXRhICovCisJaWYgKGRh dGEpCisJCW1lbWNweSgmY21kWzFdLCBkYXRhLCBzaXplKTsKKworCS8qCisJICogVGhlIGhhcmR3 YXJlIHdhbnRzIHRvIHJlY2VpdmUgYSBmcmFtZSB3aXRoIHRoZSBhZGRyZXNzIHJlZ2lzdGVyCisJ ICogY29udGFpbmVkIGluIHRoZSBmaXJzdCB0d28gYnl0ZXMuIEFzIHRoZSByZWdtYXBfd3JpdGUg ZnVuY3Rpb24KKwkgKiBhZGQgdGhlIHJlZ2lzdGVyIGFkcmVzc2UgaW4gdGhlIGZyYW1lLCB3ZSB1 c2UgdGhlIGxvdyBieXRlIGFzCisJICogZmlyc3QgZnJhbWUgYnl0ZSBmb3IgdGhlIGFkZHJlc3Mg cmVnaXN0ZXIgYW5kIHRoZSBmaXJzdAorCSAqIGRhdGEgYnl0ZSBpcyB0aGUgaGlnaCByZWdpc3Rl ciArIGxlZnQgb2YgdGhlIGNtZCB0byBzZW5kCisJICovCisJcmV0dXJuIHJlZ21hcF9idWxrX3dy aXRlKHRzLT5yZWdtYXAsIHJlZyAmIDB4RkYsIGNtZCwgc2l6ZSArIDEpOworfQorCitzdGF0aWMg dm9pZCBjeXR0c3A1X2dldF90b3VjaF9heGlzKGludCAqYXhpcywgaW50IHNpemUsIGludCBtYXgs IHU4ICp4eV9kYXRhLAorCQkJCSAgIGludCBib2ZzKQoreworCWludCBuYnl0ZTsKKworCWZvciAo bmJ5dGUgPSAwLCAqYXhpcyA9IDA7IG5ieXRlIDwgc2l6ZTsgbmJ5dGUrKykKKwkJKmF4aXMgKz0g KCh4eV9kYXRhW25ieXRlXSA+PiBib2ZzKSA8PCAobmJ5dGUgKiA4KSk7CisKKwkqYXhpcyAmPSBt YXggLSAxOworfQorCitzdGF0aWMgdm9pZCBjeXR0c3A1X2dldF90b3VjaF9yZWNvcmQoc3RydWN0 IGN5dHRzcDUgKnRzLAorCQkJCSAgICAgc3RydWN0IGN5dHRzcDVfdG91Y2ggKnRvdWNoLCB1OCAq eHlfZGF0YSkKK3sKKwlzdHJ1Y3QgY3l0dHNwNV9zeXNpbmZvICpzaSA9ICZ0cy0+c3lzaW5mbzsK KwllbnVtIGN5dHRzcDVfdGNoX2FicyBhYnM7CisKKwlmb3IgKGFicyA9IENZX1RDSF9YOyBhYnMg PCBDWV9UQ0hfTlVNX0FCUzsgYWJzKyspCisJCWN5dHRzcDVfZ2V0X3RvdWNoX2F4aXMoJnRvdWNo LT5hYnNbYWJzXSwKKwkJCQkgICAgICAgc2ktPnRjaF9hYnNbYWJzXS5zaXplLAorCQkJCSAgICAg ICBzaS0+dGNoX2Fic1thYnNdLm1heCwKKwkJCQkgICAgICAgeHlfZGF0YSArIHNpLT50Y2hfYWJz W2Fic10ub2ZzLAorCQkJCSAgICAgICBzaS0+dGNoX2Fic1thYnNdLmJvZnMpOworfQorCitzdGF0 aWMgdm9pZCBjeXR0c3A1X2dldF9tdF90b3VjaGVzKHN0cnVjdCBjeXR0c3A1ICp0cywKKwkJCQkg ICBzdHJ1Y3QgY3l0dHNwNV90b3VjaCAqdGNoLCBpbnQgbnVtX2N1cl90Y2gpCit7CisJc3RydWN0 IGN5dHRzcDVfc3lzaW5mbyAqc2kgPSAmdHMtPnN5c2luZm87CisJaW50IGksIHQgPSAwLCBvZmZz ZXQgPSAwOworCURFQ0xBUkVfQklUTUFQKGlkcywgTUFYX0NZX1RDSF9UX0lEUyk7CisJdTggKnRj aF9hZGRyOworCWludCB0bXA7CisKKwliaXRtYXBfemVybyhpZHMsIE1BWF9DWV9UQ0hfVF9JRFMp OworCW1lbXNldCh0Y2gtPmFicywgMCwgc2l6ZW9mKHRjaC0+YWJzKSk7CisKKwlzd2l0Y2ggKHRz LT5pbnB1dF9idWZbMl0pIHsKKwljYXNlIEhJRF9UT1VDSF9SRVBPUlRfSUQ6CisJCW9mZnNldCA9 IFRPVUNIX0lOUFVUX0hFQURFUl9TSVpFOworCQlicmVhazsKKwljYXNlIEhJRF9CVE5fUkVQT1JU X0lEOgorCQlvZmZzZXQgPSBCVE5fSU5QVVRfSEVBREVSX1NJWkU7CisJCWJyZWFrOworCX0KKwor CWZvciAoaSA9IDA7IGkgPCBudW1fY3VyX3RjaDsgaSsrKSB7CisJCXRjaF9hZGRyID0gdHMtPmlu cHV0X2J1ZiArIG9mZnNldCArIChpICogVE9VQ0hfUkVQT1JUX1NJWkUpOworCQljeXR0c3A1X2dl dF90b3VjaF9yZWNvcmQodHMsIHRjaCwgdGNoX2FkZHIpOworCisJCS8qIENvbnZlcnQgTUFKT1Iv TUlOT1IgZnJvbSBtbSB0byByZXNvbHV0aW9uICovCisJCXRtcCA9IHRjaC0+YWJzW0NZX1RDSF9N QUpdICogMTAwICogc2ktPnNlbnNpbmdfY29uZl9kYXRhLnJlc194OworCQl0Y2gtPmFic1tDWV9U Q0hfTUFKXSA9IHRtcCAvIHNpLT5zZW5zaW5nX2NvbmZfZGF0YS5sZW5feDsKKwkJdG1wID0gdGNo LT5hYnNbQ1lfVENIX01JTl0gKiAxMDAgKiBzaS0+c2Vuc2luZ19jb25mX2RhdGEucmVzX3g7CisJ CXRjaC0+YWJzW0NZX1RDSF9NSU5dID0gdG1wIC8gc2ktPnNlbnNpbmdfY29uZl9kYXRhLmxlbl94 OworCisJCXQgPSB0Y2gtPmFic1tDWV9UQ0hfVF07CisJCWlucHV0X210X3Nsb3QodHMtPmlucHV0 LCB0KTsKKwkJaW5wdXRfbXRfcmVwb3J0X3Nsb3Rfc3RhdGUodHMtPmlucHV0LCBNVF9UT09MX0ZJ TkdFUiwgdHJ1ZSk7CisJCV9fc2V0X2JpdCh0LCBpZHMpOworCisJCS8qIHBvc2l0aW9uIGFuZCBw cmVzc3VyZSBmaWVsZHMgKi8KKwkJdG91Y2hzY3JlZW5fcmVwb3J0X3Bvcyh0cy0+aW5wdXQsICZ0 cy0+cHJvcCwKKwkJCQkgICAgICAgdGNoLT5hYnNbQ1lfVENIX1hdLCB0Y2gtPmFic1tDWV9UQ0hf WV0sCisJCQkJICAgICAgIHRydWUpOworCQlpbnB1dF9yZXBvcnRfYWJzKHRzLT5pbnB1dCwgQUJT X01UX1BSRVNTVVJFLAorCQkJCSB0Y2gtPmFic1tDWV9UQ0hfUF0pOworCisJCS8qIEdldCB0aGUg ZXh0ZW5kZWQgdG91Y2ggZmllbGRzICovCisJCWlucHV0X3JlcG9ydF9hYnModHMtPmlucHV0LCBB QlNfTVRfVE9VQ0hfTUFKT1IsCisJCQkJIHRjaC0+YWJzW0NZX1RDSF9NQUpdKTsKKwkJaW5wdXRf cmVwb3J0X2Ficyh0cy0+aW5wdXQsIEFCU19NVF9UT1VDSF9NSU5PUiwKKwkJCQkgdGNoLT5hYnNb Q1lfVENIX01JTl0pOworCX0KKworCXRzLT5udW1fcHJ2X3JlYyA9IG51bV9jdXJfdGNoOworfQor CitzdGF0aWMgaW50IGN5dHRzcDVfbXRfYXR0ZW50aW9uKHN0cnVjdCBkZXZpY2UgKmRldikKK3sK KwlzdHJ1Y3QgY3l0dHNwNSAqdHMgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKKwlzdHJ1Y3QgY3l0 dHNwNV9zeXNpbmZvICpzaSA9ICZ0cy0+c3lzaW5mbzsKKwlpbnQgbWF4X3RjaCA9IHNpLT5zZW5z aW5nX2NvbmZfZGF0YS5tYXhfdGNoOworCXN0cnVjdCBjeXR0c3A1X3RvdWNoIHRjaDsKKwl1OCBu dW1fY3VyX3RjaDsKKworCWN5dHRzcDVfZ2V0X3RvdWNoX2F4aXMoKGludCAqKSAmbnVtX2N1cl90 Y2gsIHNpLT50Y2hfaGRyLnNpemUsCisJCQkgICAgICAgc2ktPnRjaF9oZHIubWF4LAorCQkJICAg ICAgIHRzLT5pbnB1dF9idWYgKyAzICsgc2ktPnRjaF9oZHIub2ZzLAorCQkJICAgICAgIHNpLT50 Y2hfaGRyLmJvZnMpOworCisJaWYgKG51bV9jdXJfdGNoID4gbWF4X3RjaCkgeworCQlkZXZfZXJy KGRldiwgIk51bSB0b3VjaCBlcnIgZGV0ZWN0ZWQgKG49JWQpXG4iLCBudW1fY3VyX3RjaCk7CisJ CW51bV9jdXJfdGNoID0gbWF4X3RjaDsKKwl9CisKKwlpZiAobnVtX2N1cl90Y2ggPT0gMCAmJiB0 cy0+bnVtX3Bydl9yZWMgPT0gMCkKKwkJcmV0dXJuIDA7CisKKwkvKiBleHRyYWN0IHh5X2RhdGEg Zm9yIGFsbCBjdXJyZW50bHkgcmVwb3J0ZWQgdG91Y2hlcyAqLworCWlmIChudW1fY3VyX3RjaCkK KwkJY3l0dHNwNV9nZXRfbXRfdG91Y2hlcyh0cywgJnRjaCwgbnVtX2N1cl90Y2gpOworCisJaW5w dXRfbXRfc3luY19mcmFtZSh0cy0+aW5wdXQpOworCWlucHV0X3N5bmModHMtPmlucHV0KTsKKwor CXJldHVybiAwOworfQorCitzdGF0aWMgaW50IGN5dHRzcDVfc2V0dXBfaW5wdXRfZGV2aWNlKHN0 cnVjdCBkZXZpY2UgKmRldikKK3sKKwlzdHJ1Y3QgY3l0dHNwNSAqdHMgPSBkZXZfZ2V0X2RydmRh dGEoZGV2KTsKKwlzdHJ1Y3QgY3l0dHNwNV9zeXNpbmZvICpzaSA9ICZ0cy0+c3lzaW5mbzsKKwlp bnQgbWF4X3gsIG1heF95LCBtYXhfcDsKKwlpbnQgbWF4X3hfdG1wLCBtYXhfeV90bXA7CisJaW50 IGVycm9yOworCisJbWF4X3hfdG1wID0gc2ktPnNlbnNpbmdfY29uZl9kYXRhLnJlc194OworCW1h eF95X3RtcCA9IHNpLT5zZW5zaW5nX2NvbmZfZGF0YS5yZXNfeTsKKwltYXhfeCA9IG1heF94X3Rt cCAtIDE7CisJbWF4X3kgPSBtYXhfeV90bXAgLSAxOworCW1heF9wID0gc2ktPnNlbnNpbmdfY29u Zl9kYXRhLm1heF96OworCisJaW5wdXRfc2V0X2Fic19wYXJhbXModHMtPmlucHV0LCBBQlNfTVRf UE9TSVRJT05fWCwgMCwgbWF4X3gsIDAsIDApOworCWlucHV0X3NldF9hYnNfcGFyYW1zKHRzLT5p bnB1dCwgQUJTX01UX1BPU0lUSU9OX1ksIDAsIG1heF95LCAwLCAwKTsKKwlpbnB1dF9zZXRfYWJz X3BhcmFtcyh0cy0+aW5wdXQsIEFCU19NVF9QUkVTU1VSRSwgMCwgbWF4X3AsIDAsIDApOworCisJ aW5wdXRfc2V0X2Fic19wYXJhbXModHMtPmlucHV0LCBBQlNfTVRfVE9VQ0hfTUFKT1IsIDAsIE1B WF9BUkVBLCAwLCAwKTsKKwlpbnB1dF9zZXRfYWJzX3BhcmFtcyh0cy0+aW5wdXQsIEFCU19NVF9U T1VDSF9NSU5PUiwgMCwgTUFYX0FSRUEsIDAsIDApOworCisJZXJyb3IgPSBpbnB1dF9tdF9pbml0 X3Nsb3RzKHRzLT5pbnB1dCwgc2ktPnRjaF9hYnNbQ1lfVENIX1RdLm1heCwKKwkJSU5QVVRfTVRf RFJPUF9VTlVTRUQgfCBJTlBVVF9NVF9ESVJFQ1QpOworCWlmIChlcnJvciA8IDApCisJCXJldHVy biBlcnJvcjsKKworCWVycm9yID0gaW5wdXRfcmVnaXN0ZXJfZGV2aWNlKHRzLT5pbnB1dCk7CisJ aWYgKGVycm9yIDwgMCkKKwkJZGV2X2VycihkZXYsICJFcnJvciwgZmFpbGVkIHJlZ2lzdGVyIGlu cHV0IGRldmljZSByPSVkXG4iLCBlcnJvcik7CisKKwlyZXR1cm4gZXJyb3I7Cit9CisKK3N0YXRp YyBpbnQgY3l0dHNwNV9wYXJzZV9kdF9rZXlfY29kZShzdHJ1Y3QgZGV2aWNlICpkZXYpCit7CisJ c3RydWN0IGN5dHRzcDUgKnRzID0gZGV2X2dldF9kcnZkYXRhKGRldik7CisJc3RydWN0IGN5dHRz cDVfc3lzaW5mbyAqc2kgPSAmdHMtPnN5c2luZm87CisKKwlpZiAoIXNpLT5udW1fYnRucykKKwkJ cmV0dXJuIDA7CisKKwkvKiBJbml0aWFsaXplIHRoZSBidXR0b24gdG8gUkVTRVJWRUQgKi8KKwlt ZW1zZXQzMihzaS0+a2V5X2NvZGUsIEtFWV9SRVNFUlZFRCwgIHNpLT5udW1fYnRucyk7CisKKwly ZXR1cm4gZGV2aWNlX3Byb3BlcnR5X3JlYWRfdTMyX2FycmF5KGRldiwgImxpbnV4LGtleWNvZGVz IiwKKwkJCQkgICBzaS0+a2V5X2NvZGUsIHNpLT5udW1fYnRucyk7Cit9CisKK3N0YXRpYyBpbnQg Y3l0dHNwNV9idG5fYXR0ZW50aW9uKHN0cnVjdCBkZXZpY2UgKmRldikKK3sKKwlzdHJ1Y3QgY3l0 dHNwNSAqdHMgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKKwlzdHJ1Y3QgY3l0dHNwNV9zeXNpbmZv ICpzaSA9ICZ0cy0+c3lzaW5mbzsKKwlpbnQgY3VyX2J0biwgb2Zmc2V0ID0gMDsKKwlpbnQgY3Vy X2J0bl9zdGF0ZTsKKworCXN3aXRjaCAodHMtPmlucHV0X2J1ZlsyXSkgeworCWNhc2UgSElEX1RP VUNIX1JFUE9SVF9JRDoKKwkJb2Zmc2V0ID0gVE9VQ0hfSU5QVVRfSEVBREVSX1NJWkU7CisJCWJy ZWFrOworCWNhc2UgSElEX0JUTl9SRVBPUlRfSUQ6CisJCW9mZnNldCA9IEJUTl9JTlBVVF9IRUFE RVJfU0laRTsKKwkJYnJlYWs7CisJfQorCisJaWYgKHRzLT5pbnB1dF9idWZbMl0gIT0gSElEX0JU Tl9SRVBPUlRfSUQgfHwgIXNpLT5udW1fYnRucykKKwkJcmV0dXJuIDA7CisKKwkvKiBleHRyYWN0 IGJ1dHRvbiBwcmVzcy9yZWxlYXNlIHRvdWNoIGluZm9ybWF0aW9uICovCisJZm9yIChjdXJfYnRu ID0gMDsgY3VyX2J0biA8IHNpLT5udW1fYnRuczsgY3VyX2J0bisrKSB7CisJCS8qIEdldCBjdXJy ZW50IGJ1dHRvbiBzdGF0ZSAqLworCQljdXJfYnRuX3N0YXRlID0gKHRzLT5pbnB1dF9idWZbb2Zm c2V0XSA+PiAoY3VyX2J0biAqIENZX0JJVFNfUEVSX0JUTikpCisJCQkmIENZX05VTV9CVE5fRVZF TlRfSUQ7CisKKwkJaW5wdXRfcmVwb3J0X2tleSh0cy0+aW5wdXQsIHNpLT5rZXlfY29kZVtjdXJf YnRuXSwKKwkJCQkgY3VyX2J0bl9zdGF0ZSk7CisJCWlucHV0X3N5bmModHMtPmlucHV0KTsKKwl9 CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBjeXR0c3A1X3ZhbGlkYXRlX2NtZF9yZXNw b25zZShzdHJ1Y3QgY3l0dHNwNSAqdHMsIHU4IGNvZGUpCit7CisJdTE2IHNpemUsIGNyYzsKKwl1 OCBzdGF0dXMsIHJlcG9ydF9pZDsKKwlpbnQgY29tbWFuZF9jb2RlOworCisJc2l6ZSA9IGdldF91 bmFsaWduZWRfbGUxNigmdHMtPnJlc3BvbnNlX2J1ZlswXSk7CisKKwlpZiAoIXNpemUpCisJCXJl dHVybiAwOworCisJcmVwb3J0X2lkID0gdHMtPnJlc3BvbnNlX2J1ZltISURfT1VUUFVUX1JFU1BP TlNFX1JFUE9SVF9PRkZTRVRdOworCisJc3dpdGNoIChyZXBvcnRfaWQpIHsKKwljYXNlIEhJRF9C TF9SRVNQT05TRV9SRVBPUlRfSUQ6IHsKKwkJaWYgKHRzLT5yZXNwb25zZV9idWZbNF0gIT0gSElE X09VVFBVVF9CTF9TT1ApIHsKKwkJCWRldl9lcnIodHMtPmRldiwgIkhJRCBvdXRwdXQgcmVzcG9u c2UsIHdyb25nIFNPUFxuIik7CisJCQlyZXR1cm4gLUVQUk9UTzsKKwkJfQorCisJCWlmICh0cy0+ cmVzcG9uc2VfYnVmW3NpemUgLSAxXSAhPSBISURfT1VUUFVUX0JMX0VPUCkgeworCQkJZGV2X2Vy cih0cy0+ZGV2LCAiSElEIG91dHB1dCByZXNwb25zZSwgd3JvbmcgRU9QXG4iKTsKKwkJCXJldHVy biAtRVBST1RPOworCQl9CisKKwkJY3JjID0gY3JjX2l0dV90KDB4RkZGRiwgJnRzLT5yZXNwb25z ZV9idWZbNF0sIHNpemUgLSA3KTsKKwkJaWYgKGdldF91bmFsaWduZWRfbGUxNigmdHMtPnJlc3Bv bnNlX2J1ZltzaXplIC0gM10pICE9IGNyYykgeworCQkJZGV2X2Vycih0cy0+ZGV2LCAiSElEIG91 dHB1dCByZXNwb25zZSwgd3JvbmcgQ1JDIDB4JVhcbiIsCisJCQkJY3JjKTsKKwkJCXJldHVybiAt RVBST1RPOworCQl9CisKKwkJc3RhdHVzID0gdHMtPnJlc3BvbnNlX2J1Zls1XTsKKwkJaWYgKHN0 YXR1cykgeworCQkJZGV2X2Vycih0cy0+ZGV2LCAiSElEIG91dHB1dCByZXNwb25zZSwgRVJST1I6 JWRcbiIsCisJCQkJc3RhdHVzKTsKKwkJCXJldHVybiAtRVBST1RPOworCQl9CisJCWJyZWFrOwor CX0KKwljYXNlIEhJRF9BUFBfUkVTUE9OU0VfUkVQT1JUX0lEOiB7CisJCWNvbW1hbmRfY29kZSA9 IHRzLT5yZXNwb25zZV9idWZbSElEX09VVFBVVF9SRVNQT05TRV9DTURfT0ZGU0VUXQorCQkJJiBI SURfT1VUUFVUX1JFU1BPTlNFX0NNRF9NQVNLOworCQlpZiAoY29tbWFuZF9jb2RlICE9IGNvZGUp IHsKKwkJCWRldl9lcnIodHMtPmRldiwKKwkJCQkiSElEIG91dHB1dCByZXNwb25zZSwgd3Jvbmcg Y29tbWFuZF9jb2RlOiVYXG4iLAorCQkJCWNvbW1hbmRfY29kZSk7CisJCQlyZXR1cm4gLUVQUk9U TzsKKwkJfQorCQlicmVhazsKKwl9CisJfQorCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyB2b2lk IGN5dHRzcDVfc2lfZ2V0X2J0bl9kYXRhKHN0cnVjdCBjeXR0c3A1ICp0cykKK3sKKwlzdHJ1Y3Qg Y3l0dHNwNV9zeXNpbmZvICpzaSA9ICZ0cy0+c3lzaW5mbzsKKwl1bnNpZ25lZCBpbnQgYnRucyA9 IHRzLT5yZXNwb25zZV9idWZbSElEX1NZU0lORk9fQlROX09GRlNFVF0KKwkJJiBISURfU1lTSU5G T19CVE5fTUFTSzsKKworCXNpLT5udW1fYnRucyA9IGh3ZWlnaHQ4KGJ0bnMpOworfQorCitzdGF0 aWMgaW50IGN5dHRzcDVfZ2V0X3N5c2luZm9fcmVncyhzdHJ1Y3QgY3l0dHNwNSAqdHMpCit7CisJ c3RydWN0IGN5dHRzcDVfc2Vuc2luZ19jb25mX2RhdGEgKnNjZCA9ICZ0cy0+c3lzaW5mby5zZW5z aW5nX2NvbmZfZGF0YTsKKwlzdHJ1Y3QgY3l0dHNwNV9zZW5zaW5nX2NvbmZfZGF0YV9kZXYgKnNj ZF9kZXYgPQorCQkoc3RydWN0IGN5dHRzcDVfc2Vuc2luZ19jb25mX2RhdGFfZGV2ICopCisJCSZ0 cy0+cmVzcG9uc2VfYnVmW0hJRF9TWVNJTkZPX1NFTlNJTkdfT0ZGU0VUXTsKKworCWN5dHRzcDVf c2lfZ2V0X2J0bl9kYXRhKHRzKTsKKworCXNjZC0+bWF4X3RjaCA9IHNjZF9kZXYtPm1heF9udW1f b2ZfdGNoX3Blcl9yZWZyZXNoX2N5Y2xlOworCXNjZC0+cmVzX3ggPSBnZXRfdW5hbGlnbmVkX2xl MTYoJnNjZF9kZXYtPnJlc194KTsKKwlzY2QtPnJlc195ID0gZ2V0X3VuYWxpZ25lZF9sZTE2KCZz Y2RfZGV2LT5yZXNfeSk7CisJc2NkLT5tYXhfeiA9IGdldF91bmFsaWduZWRfbGUxNigmc2NkX2Rl di0+bWF4X3opOworCXNjZC0+bGVuX3ggPSBnZXRfdW5hbGlnbmVkX2xlMTYoJnNjZF9kZXYtPmxl bl94KTsKKwlzY2QtPmxlbl95ID0gZ2V0X3VuYWxpZ25lZF9sZTE2KCZzY2RfZGV2LT5sZW5feSk7 CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBjeXR0c3A1X2hpZF9vdXRwdXRfZ2V0X3N5 c2luZm8oc3RydWN0IGN5dHRzcDUgKnRzKQoreworCWludCByYzsKKwl1OCBjbWRbSElEX09VVFBV VF9HRVRfU1lTSU5GT19TSVpFXTsKKworCS8qIEhJIGJ5dGVzIG9mIE91dHB1dCByZWdpc3RlciBh ZGRyZXNzICovCisJcHV0X3VuYWxpZ25lZF9sZTE2KEhJRF9PVVRQVVRfR0VUX1NZU0lORk9fU0la RSwgY21kKTsKKwljbWRbMl0gPSBISURfQVBQX09VVFBVVF9SRVBPUlRfSUQ7CisJY21kWzNdID0g MHgwOyAvKiBSZXNlcnZlZCAqLworCWNtZFs0XSA9IEhJRF9PVVRQVVRfR0VUX1NZU0lORk87CisK KwlyYyA9IGN5dHRzcDVfd3JpdGUodHMsIEhJRF9PVVRQVVRfUkVHLCBjbWQsCisJCQkgICBISURf T1VUUFVUX0dFVF9TWVNJTkZPX1NJWkUpOworCWlmIChyYykgeworCQlkZXZfZXJyKHRzLT5kZXYs ICJGYWlsZWQgdG8gd3JpdGUgY29tbWFuZCAlZCIsIHJjKTsKKwkJcmV0dXJuIHJjOworCX0KKwor CXJjID0gd2FpdF9mb3JfY29tcGxldGlvbl9pbnRlcnJ1cHRpYmxlX3RpbWVvdXQoJnRzLT5jbWRf ZG9uZSwKKwkJCQkJCW1zZWNzX3RvX2ppZmZpZXMoQ1lfSElEX09VVFBVVF9HRVRfU1lTSU5GT19U SU1FT1VUX01TKSk7CisJaWYgKHJjIDw9IDApIHsKKwkJZGV2X2Vycih0cy0+ZGV2LCAiSElEIG91 dHB1dCBjbWQgZXhlY3V0aW9uIHRpbWVkIG91dFxuIik7CisJCXJjID0gLUVUSU1FRE9VVDsKKwkJ cmV0dXJuIHJjOworCX0KKworCXJjID0gY3l0dHNwNV92YWxpZGF0ZV9jbWRfcmVzcG9uc2UodHMs IEhJRF9PVVRQVVRfR0VUX1NZU0lORk8pOworCWlmIChyYykgeworCQlkZXZfZXJyKHRzLT5kZXYs ICJWYWxpZGF0aW9uIG9mIHRoZSByZXNwb25zZSBmYWlsZWRcbiIpOworCQlyZXR1cm4gcmM7CisJ fQorCisJcmV0dXJuIGN5dHRzcDVfZ2V0X3N5c2luZm9fcmVncyh0cyk7Cit9CisKK3N0YXRpYyBp bnQgY3l0dHNwNV9oaWRfb3V0cHV0X2JsX2xhdW5jaF9hcHAoc3RydWN0IGN5dHRzcDUgKnRzKQor eworCWludCByYzsKKwl1OCBjbWRbSElEX09VVFBVVF9CTF9MQVVOQ0hfQVBQXTsKKwl1MTYgY3Jj OworCisJcHV0X3VuYWxpZ25lZF9sZTE2KEhJRF9PVVRQVVRfQkxfTEFVTkNIX0FQUF9TSVpFLCBj bWQpOworCWNtZFsyXSA9IEhJRF9CTF9PVVRQVVRfUkVQT1JUX0lEOworCWNtZFszXSA9IDB4MDsg LyogUmVzZXJ2ZWQgKi8KKwljbWRbNF0gPSBISURfT1VUUFVUX0JMX1NPUDsKKwljbWRbNV0gPSBI SURfT1VUUFVUX0JMX0xBVU5DSF9BUFA7CisJcHV0X3VuYWxpZ25lZF9sZTE2KDB4MDAsICZjbWRb Nl0pOworCWNyYyA9IGNyY19pdHVfdCgweEZGRkYsICZjbWRbNF0sIDQpOworCXB1dF91bmFsaWdu ZWRfbGUxNihjcmMsICZjbWRbOF0pOworCWNtZFsxMF0gPSBISURfT1VUUFVUX0JMX0VPUDsKKwor CXJjID0gY3l0dHNwNV93cml0ZSh0cywgSElEX09VVFBVVF9SRUcsIGNtZCwKKwkJCSAgIEhJRF9P VVRQVVRfQkxfTEFVTkNIX0FQUF9TSVpFKTsKKwlpZiAocmMpIHsKKwkJZGV2X2Vycih0cy0+ZGV2 LCAiRmFpbGVkIHRvIHdyaXRlIGNvbW1hbmQgJWQiLCByYyk7CisJCXJldHVybiByYzsKKwl9CisK KwlyYyA9IHdhaXRfZm9yX2NvbXBsZXRpb25faW50ZXJydXB0aWJsZV90aW1lb3V0KCZ0cy0+Y21k X2RvbmUsCisJCQkJCQltc2Vjc190b19qaWZmaWVzKENZX0hJRF9PVVRQVVRfVElNRU9VVF9NUykp OworCWlmIChyYyA8PSAwKSB7CisJCWRldl9lcnIodHMtPmRldiwgIkhJRCBvdXRwdXQgY21kIGV4 ZWN1dGlvbiB0aW1lZCBvdXRcbiIpOworCQlyYyA9IC1FVElNRURPVVQ7CisJCXJldHVybiByYzsK Kwl9CisKKwlyYyA9IGN5dHRzcDVfdmFsaWRhdGVfY21kX3Jlc3BvbnNlKHRzLCBISURfT1VUUFVU X0JMX0xBVU5DSF9BUFApOworCWlmIChyYykgeworCQlkZXZfZXJyKHRzLT5kZXYsICJWYWxpZGF0 aW9uIG9mIHRoZSByZXNwb25zZSBmYWlsZWRcbiIpOworCQlyZXR1cm4gcmM7CisJfQorCisJcmV0 dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgY3l0dHNwNV9nZXRfaGlkX2Rlc2NyaXB0b3Ioc3RydWN0 IGN5dHRzcDUgKnRzLAorCQkJCSAgICAgIHN0cnVjdCBjeXR0c3A1X2hpZF9kZXNjICpkZXNjKQor eworCXN0cnVjdCBkZXZpY2UgKmRldiA9IHRzLT5kZXY7CisJX19sZTE2IGhpZF9kZXNjX3JlZ2lz dGVyID0gSElEX0RFU0NfUkVHOworCWludCByYzsKKwl1OCBjbWRbMl07CisKKwkvKiBTZXQgSElE IGRlc2NyaXB0b3IgcmVnaXN0ZXIgKi8KKwltZW1jcHkoY21kLCAmaGlkX2Rlc2NfcmVnaXN0ZXIs IHNpemVvZihoaWRfZGVzY19yZWdpc3RlcikpOworCisJcmMgPSBjeXR0c3A1X3dyaXRlKHRzLCBI SURfREVTQ19SRUcsIE5VTEwsIDApOworCWlmIChyYykgeworCQlkZXZfZXJyKGRldiwgIkZhaWxl ZCB0byBnZXQgSElEIGRlc2NyaXB0b3IsIHJjPSVkXG4iLCByYyk7CisJCXJldHVybiByYzsKKwl9 CisKKwlyYyA9IHdhaXRfZm9yX2NvbXBsZXRpb25faW50ZXJydXB0aWJsZV90aW1lb3V0KCZ0cy0+ Y21kX2RvbmUsCisJCQkJCQltc2Vjc190b19qaWZmaWVzKENZX0hJRF9HRVRfSElEX0RFU0NSSVBU T1JfVElNRU9VVF9NUykpOworCWlmIChyYyA8PSAwKSB7CisJCWRldl9lcnIodHMtPmRldiwgIkhJ RCBnZXQgZGVzY3JpcHRvciB0aW1lZCBvdXRcbiIpOworCQlyYyA9IC1FVElNRURPVVQ7CisJCXJl dHVybiByYzsKKwl9CisKKwltZW1jcHkoZGVzYywgdHMtPnJlc3BvbnNlX2J1Ziwgc2l6ZW9mKCpk ZXNjKSk7CisKKwkvKiBDaGVjayBISUQgZGVzY3JpcHRvciBsZW5ndGggYW5kIHZlcnNpb24gKi8K KwlpZiAobGUxNl90b19jcHUoZGVzYy0+aGlkX2Rlc2NfbGVuKSAhPSBzaXplb2YoKmRlc2MpIHx8 CisJICAgIGxlMTZfdG9fY3B1KGRlc2MtPmJjZF92ZXJzaW9uKSAhPSBISURfVkVSU0lPTikgewor CQlkZXZfZXJyKGRldiwgIlVuc3VwcG9ydGVkIEhJRCB2ZXJzaW9uXG4iKTsKKwkJcmV0dXJuIC1F Tk9ERVY7CisJfQorCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgZmlsbF90Y2hfYWJzKHN0 cnVjdCBjeXR0c3A1X3RjaF9hYnNfcGFyYW1zICp0Y2hfYWJzLCBpbnQgcmVwb3J0X3NpemUsCisJ CQlpbnQgb2Zmc2V0KQoreworCXRjaF9hYnMtPm9mcyA9IG9mZnNldCAvIDg7CisJdGNoX2Ficy0+ c2l6ZSA9IHJlcG9ydF9zaXplIC8gODsKKwlpZiAocmVwb3J0X3NpemUgJSA4KQorCQl0Y2hfYWJz LT5zaXplICs9IDE7CisJdGNoX2Ficy0+bWluID0gMDsKKwl0Y2hfYWJzLT5tYXggPSAxIDw8IHJl cG9ydF9zaXplOworCXRjaF9hYnMtPmJvZnMgPSBvZmZzZXQgLSAodGNoX2Ficy0+b2ZzIDw8IDMp OworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpcnFyZXR1cm5fdCBjeXR0c3A1X2hhbmRsZV9p cnEoaW50IGlycSwgdm9pZCAqaGFuZGxlKQoreworCXN0cnVjdCBjeXR0c3A1ICp0cyA9IGhhbmRs ZTsKKwlpbnQgcmVwb3J0X2lkOworCWludCBzaXplOworCWludCBlcnJvcjsKKworCWVycm9yID0g Y3l0dHNwNV9yZWFkKHRzLCB0cy0+aW5wdXRfYnVmLCBDWV9NQVhfSU5QVVQpOworCWlmIChlcnJv cikKKwkJcmV0dXJuIElSUV9IQU5ETEVEOworCisJc2l6ZSA9IGdldF91bmFsaWduZWRfbGUxNigm dHMtPmlucHV0X2J1ZlswXSk7CisJaWYgKHNpemUgPT0gMCkgeworCQkvKiByZXNldCAqLworCQly ZXBvcnRfaWQgPSAwOworCQlzaXplID0gMjsKKwl9IGVsc2UgeworCQlyZXBvcnRfaWQgPSB0cy0+ aW5wdXRfYnVmWzJdOworCX0KKworCXN3aXRjaCAocmVwb3J0X2lkKSB7CisJY2FzZSBISURfVE9V Q0hfUkVQT1JUX0lEOgorCQljeXR0c3A1X210X2F0dGVudGlvbih0cy0+ZGV2KTsKKwkJYnJlYWs7 CisJY2FzZSBISURfQlROX1JFUE9SVF9JRDoKKwkJY3l0dHNwNV9idG5fYXR0ZW50aW9uKHRzLT5k ZXYpOworCQlicmVhazsKKwlkZWZhdWx0OgorCQkvKiBJdCBpcyBub3QgYW4gaW5wdXQgYnV0IGEg Y29tbWFuZCByZXNwb25zZSAqLworCQltZW1jcHkodHMtPnJlc3BvbnNlX2J1ZiwgdHMtPmlucHV0 X2J1Ziwgc2l6ZSk7CisJCWNvbXBsZXRlKCZ0cy0+Y21kX2RvbmUpOworCX0KKworCXJldHVybiBJ UlFfSEFORExFRDsKK30KKworc3RhdGljIGludCBjeXR0c3A1X2RlYXNzZXJ0X2ludChzdHJ1Y3Qg Y3l0dHNwNSAqdHMpCit7CisJdTE2IHNpemU7CisJdTggYnVmWzJdOworCWludCBlcnJvcjsKKwor CWVycm9yID0gcmVnbWFwX2J1bGtfcmVhZCh0cy0+cmVnbWFwLCBISURfSU5QVVRfUkVHLCBidWYs IHNpemVvZihidWYpKTsKKwlpZiAoZXJyb3IgPCAwKQorCQlyZXR1cm4gZXJyb3I7CisKKwlzaXpl ID0gZ2V0X3VuYWxpZ25lZF9sZTE2KCZidWZbMF0pOworCWlmIChzaXplID09IDIgfHwgc2l6ZSA9 PSAwKQorCQlyZXR1cm4gMDsKKworCXJldHVybiAtRUlOVkFMOworfQorCitzdGF0aWMgaW50IGN5 dHRzcDVfZmlsbF9hbGxfdG91Y2goc3RydWN0IGN5dHRzcDUgKnRzKQoreworCXN0cnVjdCBjeXR0 c3A1X3N5c2luZm8gKnNpID0gJnRzLT5zeXNpbmZvOworCisJZmlsbF90Y2hfYWJzKCZzaS0+dGNo X2Fic1tDWV9UQ0hfWF0sIFJFUE9SVF9TSVpFXzE2LAorCQkgICAgIFRPVUNIX1JFUE9SVF9ERVND X1gpOworCWZpbGxfdGNoX2Ficygmc2ktPnRjaF9hYnNbQ1lfVENIX1ldLCBSRVBPUlRfU0laRV8x NiwKKwkJICAgICBUT1VDSF9SRVBPUlRfREVTQ19ZKTsKKwlmaWxsX3RjaF9hYnMoJnNpLT50Y2hf YWJzW0NZX1RDSF9QXSwgUkVQT1JUX1NJWkVfOCwKKwkJICAgICBUT1VDSF9SRVBPUlRfREVTQ19Q KTsKKwlmaWxsX3RjaF9hYnMoJnNpLT50Y2hfYWJzW0NZX1RDSF9UXSwgUkVQT1JUX1NJWkVfNSwK KwkJICAgICBUT1VDSF9SRVBPUlRfREVTQ19DT05UQUNUSUQpOworCWZpbGxfdGNoX2Ficygmc2kt PnRjaF9oZHIsIFJFUE9SVF9TSVpFXzUsCisJCSAgICAgVE9VQ0hfUkVQT1JUX0RFU0NfSERSX0NP TlRBQ1RDT1VOVCk7CisJZmlsbF90Y2hfYWJzKCZzaS0+dGNoX2Fic1tDWV9UQ0hfTUFKXSwgUkVQ T1JUX1NJWkVfOCwKKwkJICAgICBUT1VDSF9SRVBPUlRfREVTQ19NQUopOworCWZpbGxfdGNoX2Fi cygmc2ktPnRjaF9hYnNbQ1lfVENIX01JTl0sIFJFUE9SVF9TSVpFXzgsCisJCSAgICAgVE9VQ0hf UkVQT1JUX0RFU0NfTUlOKTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IGN5dHRzcDVf c3RhcnR1cChzdHJ1Y3QgY3l0dHNwNSAqdHMpCit7CisJaW50IGVycm9yOworCisJZXJyb3IgPSBj eXR0c3A1X2RlYXNzZXJ0X2ludCh0cyk7CisJaWYgKGVycm9yKSB7CisJCWRldl9lcnIodHMtPmRl diwgIkVycm9yIG9uIGRlYXNzZXJ0IGludCByPSVkXG4iLCBlcnJvcik7CisJCXJldHVybiAtRU5P REVWOworCX0KKworCS8qCisJICogTGF1bmNoIHRoZSBhcHBsaWNhdGlvbiBhcyB0aGUgZGV2aWNl IHN0YXJ0cyBpbiBib290bG9hZGVyIG1vZGUKKwkgKiBiZWNhdXNlIG9mIGEgcG93ZXItb24tcmVz ZXQKKwkgKi8KKwllcnJvciA9IGN5dHRzcDVfaGlkX291dHB1dF9ibF9sYXVuY2hfYXBwKHRzKTsK KwlpZiAoZXJyb3IgPCAwKSB7CisJCWRldl9lcnIodHMtPmRldiwgIkVycm9yIG9uIGxhdW5jaCBh cHAgcj0lZFxuIiwgZXJyb3IpOworCQlyZXR1cm4gZXJyb3I7CisJfQorCisJZXJyb3IgPSBjeXR0 c3A1X2dldF9oaWRfZGVzY3JpcHRvcih0cywgJnRzLT5oaWRfZGVzYyk7CisJaWYgKGVycm9yIDwg MCkgeworCQlkZXZfZXJyKHRzLT5kZXYsICJFcnJvciBvbiBnZXR0aW5nIEhJRCBkZXNjcmlwdG9y IHI9JWRcbiIsIGVycm9yKTsKKwkJcmV0dXJuIGVycm9yOworCX0KKworCWVycm9yID0gY3l0dHNw NV9maWxsX2FsbF90b3VjaCh0cyk7CisJaWYgKGVycm9yIDwgMCkgeworCQlkZXZfZXJyKHRzLT5k ZXYsICJFcnJvciBvbiByZXBvcnQgZGVzY3JpcHRvciByPSVkXG4iLCBlcnJvcik7CisJCXJldHVy biBlcnJvcjsKKwl9CisKKwllcnJvciA9IGN5dHRzcDVfaGlkX291dHB1dF9nZXRfc3lzaW5mbyh0 cyk7CisJaWYgKGVycm9yKSB7CisJCWRldl9lcnIodHMtPmRldiwgIkVycm9yIG9uIGdldHRpbmcg c3lzaW5mbyByPSVkXG4iLCBlcnJvcik7CisJCXJldHVybiBlcnJvcjsKKwl9CisKKwlyZXR1cm4g ZXJyb3I7Cit9CisKK3N0YXRpYyB2b2lkIGN5dHRzcDVfY2xlYW51cCh2b2lkICpkYXRhKQorewor CXN0cnVjdCBjeXR0c3A1ICp0cyA9IGRhdGE7CisKKwlyZWd1bGF0b3JfZGlzYWJsZSh0cy0+dmRk KTsKK30KKworc3RhdGljIGludCBjeXR0c3A1X3Byb2JlKHN0cnVjdCBkZXZpY2UgKmRldiwgc3Ry dWN0IHJlZ21hcCAqcmVnbWFwLCBpbnQgaXJxLAorCQkJIGNvbnN0IGNoYXIgKm5hbWUpCit7CisJ c3RydWN0IGN5dHRzcDUgKnRzOworCXN0cnVjdCBjeXR0c3A1X3N5c2luZm8gKnNpOworCWludCBl cnJvciwgaTsKKworCXRzID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9mKCp0cyksIEdGUF9LRVJO RUwpOworCWlmICghdHMpCisJCXJldHVybiAtRU5PTUVNOworCisJLyogSW5pdGlhbGl6ZSBkZXZp Y2UgaW5mbyAqLworCXRzLT5yZWdtYXAgPSByZWdtYXA7CisJdHMtPmRldiA9IGRldjsKKwlzaSA9 ICZ0cy0+c3lzaW5mbzsKKwlkZXZfc2V0X2RydmRhdGEoZGV2LCB0cyk7CisKKwlpbml0X2NvbXBs ZXRpb24oJnRzLT5jbWRfZG9uZSk7CisKKwkvKiBQb3dlciB1cCB0aGUgZGV2aWNlICovCisJdHMt PnZkZCA9IGRldm1fcmVndWxhdG9yX2dldChkZXYsICJ2ZGQiKTsKKwlpZiAoSVNfRVJSKHRzLT52 ZGQpKSB7CisJCWVycm9yID0gUFRSX0VSUih0cy0+dmRkKTsKKwkJcmV0dXJuIGVycm9yOworCX0K KworCWVycm9yID0gZGV2bV9hZGRfYWN0aW9uX29yX3Jlc2V0KGRldiwgY3l0dHNwNV9jbGVhbnVw LCB0cyk7CisJaWYgKGVycm9yKSB7CisJCXJldHVybiBlcnJvcjsKKwl9CisKKwllcnJvciA9IHJl Z3VsYXRvcl9lbmFibGUodHMtPnZkZCk7CisJaWYgKGVycm9yKSB7CisJCXJldHVybiBlcnJvcjsK Kwl9CisKKwl0cy0+aW5wdXQgPSBkZXZtX2lucHV0X2FsbG9jYXRlX2RldmljZShkZXYpOworCWlm ICghdHMtPmlucHV0KSB7CisJCWRldl9lcnIoZGV2LCAiRXJyb3IsIGZhaWxlZCB0byBhbGxvY2F0 ZSBpbnB1dCBkZXZpY2VcbiIpOworCQlyZXR1cm4gLUVOT0RFVjsKKwl9CisKKwl0cy0+aW5wdXQt Pm5hbWUgPSAiY3l0dHNwNSI7CisJc2NucHJpbnRmKHRzLT5waHlzLCBzaXplb2YodHMtPnBoeXMp LCAiJXMvaW5wdXQwIiwgZGV2X25hbWUoZGV2KSk7CisJdHMtPmlucHV0LT5waHlzID0gdHMtPnBo eXM7CisJaW5wdXRfc2V0X2RydmRhdGEodHMtPmlucHV0LCB0cyk7CisKKwkvKiBSZXNldCB0aGUg Z3BpbyB0byBiZSBpbiBhIHJlc2V0IHN0YXRlICovCisJdHMtPnJlc2V0X2dwaW8gPSBkZXZtX2dw aW9kX2dldF9vcHRpb25hbChkZXYsICJyZXNldCIsIEdQSU9EX09VVF9ISUdIKTsKKwlpZiAoSVNf RVJSKHRzLT5yZXNldF9ncGlvKSkgeworCQllcnJvciA9IFBUUl9FUlIodHMtPnJlc2V0X2dwaW8p OworCQlkZXZfZXJyKGRldiwgIkZhaWxlZCB0byByZXF1ZXN0IHJlc2V0IGdwaW8sIGVycm9yICVk XG4iLCBlcnJvcik7CisJCXJldHVybiBlcnJvcjsKKwl9CisJZ3Bpb2Rfc2V0X3ZhbHVlKHRzLT5y ZXNldF9ncGlvLCAwKTsKKworCS8qIE5lZWQgYSBkZWxheSB0byBoYXZlIGRldmljZSB1cCAqLwor CW1zbGVlcCgyMCk7CisKKwllcnJvciA9IGRldm1fcmVxdWVzdF90aHJlYWRlZF9pcnEoZGV2LCBp cnEsIE5VTEwsIGN5dHRzcDVfaGFuZGxlX2lycSwKKwkJCQkgICAgICAgSVJRRl9PTkVTSE9ULCBu YW1lLCB0cyk7CisJaWYgKGVycm9yKSB7CisJCWRldl9lcnIoZGV2LCAidW5hYmxlIHRvIHJlcXVl c3QgSVJRXG4iKTsKKwkJcmV0dXJuIGVycm9yOworCX0KKworCWVycm9yID0gY3l0dHNwNV9zdGFy dHVwKHRzKTsKKwlpZiAoZXJyb3IpIHsKKwkJZGV2X2Vycih0cy0+ZGV2LCAiRmFpbCBpbml0aWFs IHN0YXJ0dXAgcj0lZFxuIiwgZXJyb3IpOworCQlyZXR1cm4gZXJyb3I7CisJfQorCisJZXJyb3Ig PSBjeXR0c3A1X3BhcnNlX2R0X2tleV9jb2RlKGRldik7CisJaWYgKGVycm9yIDwgMCkgeworCQlk ZXZfZXJyKHRzLT5kZXYsICJFcnJvciB3aGlsZSBwYXJzaW5nIGR0cyAlZFxuIiwgZXJyb3IpOwor CQlyZXR1cm4gZXJyb3I7CisJfQorCisJdG91Y2hzY3JlZW5fcGFyc2VfcHJvcGVydGllcyh0cy0+ aW5wdXQsIHRydWUsICZ0cy0+cHJvcCk7CisKKwlfX3NldF9iaXQoRVZfS0VZLCB0cy0+aW5wdXQt PmV2Yml0KTsKKwlmb3IgKGkgPSAwOyBpIDwgc2ktPm51bV9idG5zOyBpKyspCisJCV9fc2V0X2Jp dChzaS0+a2V5X2NvZGVbaV0sIHRzLT5pbnB1dC0+a2V5Yml0KTsKKworCXJldHVybiBjeXR0c3A1 X3NldHVwX2lucHV0X2RldmljZShkZXYpOworfQorCitzdGF0aWMgaW50IGN5dHRzcDVfaTJjX3By b2JlKHN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQsCisJCQkgICAgIGNvbnN0IHN0cnVjdCBpMmNf ZGV2aWNlX2lkICppZCkKK3sKKwlzdHJ1Y3QgcmVnbWFwICpyZWdtYXA7CisJc3RhdGljIGNvbnN0 IHN0cnVjdCByZWdtYXBfY29uZmlnIGNvbmZpZyA9IHsKKwkJLnJlZ19iaXRzID0gOCwKKwkJLnZh bF9iaXRzID0gOCwKKwl9OworCisJcmVnbWFwID0gZGV2bV9yZWdtYXBfaW5pdF9pMmMoY2xpZW50 LCAmY29uZmlnKTsKKwlpZiAoSVNfRVJSKHJlZ21hcCkpIHsKKwkJZGV2X2VycigmY2xpZW50LT5k ZXYsICJyZWdtYXAgYWxsb2NhdGlvbiBmYWlsZWQ6ICVsZFxuIiwKKwkJCVBUUl9FUlIocmVnbWFw KSk7CisJCXJldHVybiBQVFJfRVJSKHJlZ21hcCk7CisJfQorCisJcmV0dXJuIGN5dHRzcDVfcHJv YmUoJmNsaWVudC0+ZGV2LCByZWdtYXAsIGNsaWVudC0+aXJxLCBjbGllbnQtPm5hbWUpOworfQor CitzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCBjeXR0c3A1X29mX21hdGNoW10gPSB7 CisJeyAuY29tcGF0aWJsZSA9ICJjeXByZXNzLHR0MjEwMDAiLCB9LAorCXsgfQorfTsKK01PRFVM RV9ERVZJQ0VfVEFCTEUob2YsIGN5dHRzcDVfb2ZfbWF0Y2gpOworCitzdGF0aWMgY29uc3Qgc3Ry dWN0IGkyY19kZXZpY2VfaWQgY3l0dHNwNV9pMmNfaWRbXSA9IHsKKwl7IENZVFRTUDVfTkFNRSwg MCwgfSwKKwl7IH0KK307CitNT0RVTEVfREVWSUNFX1RBQkxFKGkyYywgY3l0dHNwNV9pMmNfaWQp OworCitzdGF0aWMgc3RydWN0IGkyY19kcml2ZXIgY3l0dHNwNV9pMmNfZHJpdmVyID0geworCS5k cml2ZXIgPSB7CisJCS5uYW1lID0gQ1lUVFNQNV9OQU1FLAorCQkub2ZfbWF0Y2hfdGFibGUgPSBj eXR0c3A1X29mX21hdGNoLAorCX0sCisJLnByb2JlID0gY3l0dHNwNV9pMmNfcHJvYmUsCisJLmlk X3RhYmxlID0gY3l0dHNwNV9pMmNfaWQsCit9OworbW9kdWxlX2kyY19kcml2ZXIoY3l0dHNwNV9p MmNfZHJpdmVyKTsKKworTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOworTU9EVUxFX0RFU0NSSVBUSU9O KCJUb3VjaHNjcmVlbiBkcml2ZXIgZm9yIEN5cHJlc3MgVHJ1ZVRvdWNoIEdlbiA1IFByb2R1Y3Qi KTsKK01PRFVMRV9BVVRIT1IoIk15bMOobmUgSm9zc2VyYW5kIDxteWxlbmUuam9zc2VyYW5kQGJv b3RsaW4uY29tPiIpOwotLSAKMi4zNS4xCgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX18KbGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJt LWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21h aWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5lbAo=