From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755004AbbBLGHp (ORCPT ); Thu, 12 Feb 2015 01:07:45 -0500 Received: from sism000.sis.com ([210.242.182.187]:20221 "EHLO sism02.sis.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751266AbbBLGHk (ORCPT ); Thu, 12 Feb 2015 01:07:40 -0500 X-MimeOLE: Produced By Microsoft Exchange V6.5 Content-class: urn:content-classes:message MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Subject: RE: [PATCH 1/2] INPUT/HID: add touch support for SiS touch driver Date: Thu, 12 Feb 2015 14:07:21 +0800 Message-ID: <8322374EB97AA24A95D0DDBFC8F1CA1DCB07F9@SISMBEV01.sis.com.tw> In-Reply-To: X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: [PATCH 1/2] INPUT/HID: add touch support for SiS touch driver Thread-Index: AdAx6Sgom/+yWR86TaS/vBgKwo6UAwT4m7pQ References: <8322374EB97AA24A95D0DDBFC8F1CA1DBF987B@SISMBEV01.sis.com.tw><1421063449.12454.17.camel@linux-0dmf.site><8322374EB97AA24A95D0DDBFC8F1CA1DBF9DE5@SISMBEV01.sis.com.tw><8322374EB97AA24A95D0DDBFC8F1CA1DBF9E1B@SISMBEV01.sis.com.tw><1421413862.17198.23.camel@linux-0dmf.site> From: =?UTF-8?B?5pu+5am36JGzICh0YW1teV90c2VuZyk=?= To: "Dmitry Torokhov" , "Oliver Neukum" Cc: "lkml" , , X-OriginalArrivalTime: 12 Feb 2015 06:07:22.0310 (UTC) FILETIME=[2A509660:01D0468A] X-TM-AS-Product-Ver: SMEX-10.2.0.3176-7.500.1018-21324.002 X-TM-AS-Result: No--7.665900-0.000000-31 X-TM-AS-User-Approved-Sender: Yes X-TM-AS-User-Blocked-Sender: No X-Received-IP: 192.168.50.86 X-Envelope-From: X-Sherlock-Send: MailFilter (sism02.sis.com) X-License: 1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from base64 to 8bit by nfs id t1C67oA1027697 Hi, I've checked the coding style and modified the i2c and hid touch driver for sis touch controller. Please help review them. Thanks a lot. Tammy ----- Here is the sis i2c driver in input: linux-3.18.5/drivers/input/touchscreen/Kconfig | 7 + linux-3.18.5/drivers/input/touchscreen/Makefile | 1 + linux-3.18.5/drivers/input/touchscreen/sis_i2c.c | 1032 ++++++++++++++++++++++ linux-3.18.5/drivers/input/touchscreen/sis_i2c.h | 173 ++++ 4 files changed, 1213 insertions(+) ----- diff --git a/linux-3.18.5/drivers/input/touchscreen/Kconfig b/linux-3.18.5/drivers/input/touchscreen/Kconfig index e1d8003..5093ccc 100644 --- a/linux-3.18.5/drivers/input/touchscreen/Kconfig +++ b/linux-3.18.5/drivers/input/touchscreen/Kconfig @@ -962,4 +962,11 @@ config TOUCHSCREEN_ZFORCE To compile this driver as a module, choose M here: the module will be called zforce_ts. +config TOUCHSCREEN_SIS_I2C + tristate "SiS 9200 family I2C touchscreen driver" + depends on I2C + default n + help + This enables support for SiS 9200 family over I2C based touchscreens. + endif diff --git a/linux-3.18.5/drivers/input/touchscreen/Makefile b/linux-3.18.5/drivers/input/touchscreen/Makefile index 090e61c..25cfd9f 100644 --- a/linux-3.18.5/drivers/input/touchscreen/Makefile +++ b/linux-3.18.5/drivers/input/touchscreen/Makefile @@ -79,3 +79,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o +obj-$(CONFIG_TOUCHSCREEN_SIS_I2C) += sis_i2c.o diff --git a/linux-3.18.5/drivers/input/touchscreen/sis_i2c.c b/linux-3.18.5/drivers/input/touchscreen/sis_i2c.c new file mode 100644 index 0000000..260a7b6 --- /dev/null +++ b/linux-3.18.5/drivers/input/touchscreen/sis_i2c.c @@ -0,0 +1,1032 @@ +/* drivers/input/touchscreen/sis_i2c.c + * - I2C Touch panel driver for SiS 9200 family + * + * Copyright (C) 2011 SiS, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif +#include +#include +#include +#include +#include +#include +#include "sis_i2c.h" +#include +#include +#include +#include +#include +#include + +#ifdef _STD_RW_IO +#include +#include +#include +#define DEVICE_NAME "sis_aegis_touch_device" +static const int sis_char_devs_count = 1; /* device count */ +static int sis_char_major; +static struct cdev sis_char_cdev; +static struct class *sis_char_class; +#endif + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { SIS_SLAVE_ADDR, I2C_CLIENT_END }; +static struct workqueue_struct *sis_wq; +struct sis_ts_data *ts_bak; +struct sisTP_driver_data *TPInfo; +static void sis_tpinfo_clear(struct sisTP_driver_data *TPInfo, int max); + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void sis_ts_early_suspend(struct early_suspend *h); +static void sis_ts_late_resume(struct early_suspend *h); +#endif + +#ifdef _CHECK_CRC +static const unsigned short crc16tab[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +static uint16_t cal_crc(char *cmd, int start, int end) +{ + int i = 0; + uint16_t crc = 0; + + for (i = start; i <= end ; i++) + crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd[i]) & 0x00FF]; + return crc; +} +#endif + +#ifdef _DEBUG_PACKAGE +static void PrintBuffer(int start, int length, char *buf) +{ + int i; + + for (i = start; i < length; i++) { + pr_info("%02x ", buf[i]); + if (i != 0 && i % 30 == 0) + pr_info("\n"); + } + pr_info("\n"); +} +#endif + +static int sis_command_for_write(struct i2c_client *client, int wlength, + unsigned char *wdata) +{ + int ret = SIS_ERR; + struct i2c_msg msg; + + msg.addr = client->addr; + msg.flags = 0; /*Write*/ + msg.len = wlength; + msg.buf = (unsigned char *)wdata; + ret = i2c_transfer(client->adapter, &msg, 1); + return ret; +} + +static int sis_command_for_read(struct i2c_client *client, int rlength, + unsigned char *rdata) +{ + int ret = SIS_ERR; + struct i2c_msg msg; + + msg.addr = client->addr; + msg.flags = I2C_M_RD; /*Read*/ + msg.len = rlength; + msg.buf = rdata; + ret = i2c_transfer(client->adapter, &msg, 1); + return ret; +} + +static int sis_cul_unit(uint8_t report_id) +{ + int ret = NORMAL_LEN_PER_POINT; + + if (report_id != ALL_IN_ONE_PACKAGE) { + if (IS_AREA(report_id) /*&& IS_TOUCH(report_id)*/) + ret += AREA_LEN_PER_POINT; + if (IS_PRESSURE(report_id)) + ret += PRESSURE_LEN_PER_POINT; + } + + return ret; +} + +static int sis_ReadPacket(struct i2c_client *client, uint8_t cmd, uint8_t *buf) +{ + uint8_t tmpbuf[MAX_BYTE] = {0}; /*MAX_BYTE = 64;*/ + int ret = SIS_ERR; + int touchnum = 0; + int p_count = 0; + int touc_formate_id = 0; + int locate = 0; + bool read_first = true; + /* + * New i2c format + * buf[0] = Low 8 bits of byte count value + * buf[1] = High 8 bits of byte counte value + * buf[2] = Report ID + * buf[touch num * 6 + 2 ] = Touch informations; + * 1 touch point has 6 bytes, it could be none if no touch + * buf[touch num * 6 + 3] = Touch numbers + * + * One touch point information include 6 bytes, the order is + * + * 1. status = touch down or touch up + * 2. id = finger id + * 3. x axis low 8 bits + * 4. x axis high 8 bits + * 5. y axis low 8 bits + * 6. y axis high 8 bits + * */ + do { + if (locate >= PACKET_BUFFER_SIZE) { + pr_err("sis_ReadPacket: Buf Overflow\n"); + return SIS_ERR; + } + ret = sis_command_for_read(client, MAX_BYTE, tmpbuf); +#ifdef _DEBUG_PACKAGE + pr_info("chaoban test: Buf_Data [0~63]\n"); + PrintBuffer(0, 64, tmpbuf); +#endif + if (ret < 0) { + pr_err("sis_ReadPacket: i2c transfer error\n"); + return ret; + } + /*error package length of receiving data*/ + else if (tmpbuf[P_BYTECOUNT] > MAX_BYTE) { + pr_err("sis_ReadPacket: Error Bytecount\n"); + return SIS_ERR; + } + if (read_first) { + /*access NO TOUCH event unless BUTTON NO TOUCH event*/ + if (tmpbuf[P_BYTECOUNT] == 0/*NO_TOUCH_BYTECOUNT*/) + return 0; /*touchnum is 0*/ + } + /*skip parsing data when two devices are registered + * at the same slave address*/ + /*parsing data when P_REPORT_ID && 0xf is TOUCH_FORMAT + * or P_REPORT_ID is ALL_IN_ONE_PACKAGE*/ + touc_formate_id = tmpbuf[P_REPORT_ID] & 0xf; + if ((touc_formate_id != TOUCH_FORMAT) + && (touc_formate_id != HIDI2C_FORMAT) + && (tmpbuf[P_REPORT_ID] != ALL_IN_ONE_PACKAGE)) { + pr_err("sis_ReadPacket: Error Report_ID\n"); + return SIS_ERR; + } + p_count = (int) tmpbuf[P_BYTECOUNT] - 1; /*start from 0*/ + if (tmpbuf[P_REPORT_ID] != ALL_IN_ONE_PACKAGE) { + if (IS_TOUCH(tmpbuf[P_REPORT_ID])) { + p_count -= BYTE_CRC_I2C;/*delete 2 byte crc*/ + } else if (IS_HIDI2C(tmpbuf[P_REPORT_ID])) { + p_count -= BYTE_CRC_HIDI2C; + } else { /*should not be happen*/ + pr_err("sis_ReadPacket: delete crc error\n"); + return SIS_ERR; + } + if (IS_SCANTIME(tmpbuf[P_REPORT_ID])) + p_count -= BYTE_SCANTIME; + } + /*else {}*/ /*For ALL_IN_ONE_PACKAGE*/ + if (read_first) { + touchnum = tmpbuf[p_count]; + } else { + if (tmpbuf[p_count] != 0) { + pr_err("sis_ReadPacket: get error package\n"); + return SIS_ERR; + } + } + +#ifdef _CHECK_CRC + /* HID over I2C data foramt and no touch packet without CRC */ + if ((touc_formate_id != HIDI2C_FORMAT) && + (tmpbuf[P_BYTECOUNT] > 3)) { + int crc_end = p_count + (IS_SCANTIME( + tmpbuf[P_REPORT_ID]) * 2); + uint16_t buf_crc = cal_crc( + tmpbuf, 2, crc_end);/*sub bytecount(2 byte)*/ + int l_package_crc = (IS_SCANTIME( + tmpbuf[P_REPORT_ID]) * 2) + p_count + 1; + uint16_t package_crc = le16_to_cpu(get_unaligned_le16( + &tmpbuf[l_package_crc])); + + if (buf_crc != package_crc) { + pr_err("sis_ReadPacket: CRC Error\n"); + return SIS_ERR; + } + } +#endif + memcpy(&buf[locate], &tmpbuf[0], 64); + /*Buf_Data [0~63] [64~128]*/ + locate += 64; + read_first = false; + } while (tmpbuf[P_REPORT_ID] != ALL_IN_ONE_PACKAGE && + tmpbuf[p_count] > 5); + return touchnum; +} + +#ifdef _INT_MODE_1 +static void ts_report_key(struct i2c_client *client, uint8_t keybit_state) +{ + int i = 0; + uint8_t diff_keybit_state = 0x0; + /*check keybit_state is difference with pre_keybit_state*/ + uint8_t key_value = 0x0; /*button location for binary*/ + uint8_t key_pressed = 0x0; /*button is up or down*/ + struct sis_ts_data *ts = i2c_get_clientdata(client); + + if (!ts) { + pr_err("%s error: Missing Platform Data!\n", __func__); + return; + } + + diff_keybit_state = TPInfo->pre_keybit_state ^ keybit_state; + + if (diff_keybit_state) { + for (i = 0; i < BUTTON_KEY_COUNT; i++) { + if ((diff_keybit_state >> i) & 0x01) { + key_value = diff_keybit_state & (0x01 << i); + key_pressed = (keybit_state >> i) & 0x01; + switch (key_value) { + case MSK_COMP: + input_report_key(ts->input_dev, + KEY_COMPOSE, key_pressed); + break; + case MSK_BACK: + input_report_key(ts->input_dev, + KEY_BACK, key_pressed); + break; + case MSK_MENU: + input_report_key(ts->input_dev, + KEY_MENU, key_pressed); + break; + case MSK_HOME: + input_report_key(ts->input_dev, + KEY_HOME, key_pressed); + break; + case MSK_NOBTN: + /*Release the button if it touched.*/ + default: + break; + } + } + } + TPInfo->pre_keybit_state = keybit_state; + } +} +#endif + +static void sis_ts_work_func(struct work_struct *work) +{ + struct sis_ts_data *ts = container_of(work, struct sis_ts_data, work); + int ret = SIS_ERR; + int point_unit; + uint8_t buf[PACKET_BUFFER_SIZE] = {0}; + uint8_t i = 0, fingers = 0; + uint8_t px = 0, py = 0, pstatus = 0; + uint8_t p_area = 0; + uint8_t p_preasure = 0; + bool all_touch_up = true; + + mutex_lock(&ts->mutex_wq); + /* I2C or SMBUS block data read */ + ret = sis_ReadPacket(ts->client, SIS_CMD_NORMAL, buf); + /*Error Number*/ + if (ret < 0) + goto err_free_allocate; + /*access NO TOUCH event unless BUTTON NO TOUCH event*/ + else if (ret == 0) { + fingers = 0; + sis_tpinfo_clear(TPInfo, MAX_FINGERS); + goto label_send_report; + /*need to report input_mt_sync()*/ + } + sis_tpinfo_clear(TPInfo, MAX_FINGERS); + + /*Parser and Get the sis9200 data*/ + point_unit = sis_cul_unit(buf[P_REPORT_ID]); + fingers = ret; + + TPInfo->fingers = fingers = (fingers > MAX_FINGERS ? 0 : fingers); + + /*fingers 10 = 0 ~ 9*/ + for (i = 0; i < fingers; i++) { + if ((buf[P_REPORT_ID] != ALL_IN_ONE_PACKAGE) && (i >= 5)) { + /*Calc point status*/ + pstatus = BYTE_BYTECOUNT + BYTE_ReportID + + ((i - 5) * point_unit); + pstatus += 64; + } else { + pstatus = BYTE_BYTECOUNT + BYTE_ReportID + + (i * point_unit); + /*Calc point status*/ + } + px = pstatus + 2; /*Calc point x_coord*/ + py = px + 2; /*Calc point y_coord*/ + if ((buf[pstatus]) == TOUCHUP) { + TPInfo->pt[i].Width = 0; + TPInfo->pt[i].Height = 0; + TPInfo->pt[i].Pressure = 0; + } else if (buf[P_REPORT_ID] == ALL_IN_ONE_PACKAGE + && (buf[pstatus]) == TOUCHDOWN) { + TPInfo->pt[i].Width = 1; + TPInfo->pt[i].Height = 1; + TPInfo->pt[i].Pressure = 1; + } else if ((buf[pstatus]) == TOUCHDOWN) { + p_area = py + 2; + p_preasure = py + 2 + (IS_AREA(buf[P_REPORT_ID]) * 2); + /*area*/ + if (IS_AREA(buf[P_REPORT_ID])) { + TPInfo->pt[i].Width = buf[p_area]; + TPInfo->pt[i].Height = buf[p_area + 1]; + } else { + TPInfo->pt[i].Width = 1; + TPInfo->pt[i].Height = 1; + } + /*preasure*/ + if (IS_PRESSURE(buf[P_REPORT_ID])) + TPInfo->pt[i].Pressure = (buf[p_preasure]); + else + TPInfo->pt[i].Pressure = 1; + } else { + pr_err("sis_ts_work_func: Error Touch Status\n"); + goto err_free_allocate; + } + TPInfo->pt[i].id = (buf[pstatus + 1]); + TPInfo->pt[i].x = le16_to_cpu(get_unaligned_le16(&buf[px])); + TPInfo->pt[i].y = le16_to_cpu(get_unaligned_le16(&buf[py])); + } + +#ifdef _DEBUG_REPORT + for (i = 0; i < TPInfo->fingers; i++) + pr_info("chaoban test: i = %d, id = %d, x = %d, y = %d, pstatus = %d, width = %d, height = %d, pressure = %d\n", + i, TPInfo->pt[i].id, TPInfo->pt[i].x, TPInfo->pt[i].y, + buf[pstatus], TPInfo->pt[i].Width, TPInfo->pt[i].Height, + TPInfo->pt[i].Pressure); +#endif +label_send_report: +/* Report co-ordinates to the multi-touch stack */ + for (i = 0; ((i < TPInfo->fingers) && (i < MAX_FINGERS)); i++) { + if (TPInfo->pt[i].Pressure) { + TPInfo->pt[i].Width *= AREA_UNIT; + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, + TPInfo->pt[i].Width); + TPInfo->pt[i].Height *= AREA_UNIT; + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MINOR, + TPInfo->pt[i].Height); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, + TPInfo->pt[i].Pressure); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, + TPInfo->pt[i].x); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, + TPInfo->pt[i].y); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, + TPInfo->pt[i].id); + /*Android 2.3*/ + input_mt_sync(ts->input_dev); + all_touch_up = false; + } + if (i == (TPInfo->fingers - 1) && all_touch_up == true) + input_mt_sync(ts->input_dev); + } + if (TPInfo->fingers == 0) + input_mt_sync(ts->input_dev); + input_sync(ts->input_dev); + +err_free_allocate: + + if (ts->use_irq) { +#ifdef _INT_MODE_1 /*case 1 mode*/ + /*TODO: After interrupt status low, + * read i2c bus data by polling, + * until interrupt status is high*/ + ret = gpio_get_value(GPIO_IRQ); + /*interrupt pin is still LOW, + * read data until interrupt pin is released.*/ + if (!ret) + hrtimer_start(&ts->timer, ktime_set(0, TIMER_NS), + HRTIMER_MODE_REL); + else { + if (TPInfo->pre_keybit_state) + /*clear for interrupt*/ + ts_report_key(ts->client, 0x0); + + if (irqd_irq_disabled(&ts->desc->irq_data)) + enable_irq(ts->client->irq); + } +#else /*case 2 mode*/ + if (irqd_irq_disabled(&ts->desc->irq_data)) + enable_irq(ts->client->irq); +#endif + } + + mutex_unlock(&ts->mutex_wq); +} + +static void sis_tpinfo_clear(struct sisTP_driver_data *TPInfo, int max) +{ + int i = 0; + + for (i = 0; i < max; i++) { + TPInfo->pt[i].id = -1; + TPInfo->pt[i].x = 0; + TPInfo->pt[i].y = 0; + TPInfo->pt[i].Pressure = 0; + TPInfo->pt[i].Width = 0; + } + TPInfo->id = 0x0; + TPInfo->fingers = 0; +} + +static enum hrtimer_restart sis_ts_timer_func(struct hrtimer *timer) +{ + struct sis_ts_data *ts = container_of(timer, struct sis_ts_data, timer); + + queue_work(sis_wq, &ts->work); + if (!ts->use_irq) /*For Polling mode*/ + hrtimer_start(&ts->timer, ktime_set(0, TIMER_NS), HRTIMER_MODE_REL); + return HRTIMER_NORESTART; +} + +static irqreturn_t sis_ts_irq_handler(int irq, void *dev_id) +{ + struct sis_ts_data *ts = dev_id; + + if (!irqd_irq_disabled(&ts->desc->irq_data)) + disable_irq_nosync(ts->client->irq); + queue_work(sis_wq, &ts->work); + return IRQ_HANDLED; +} + +static int initial_irq(void) +{ + int ret = 0; +#ifdef _I2C_INT_ENABLE + /* initialize gpio and interrupt pins */ + /*ex. GPIO_133 for interrupt mode*/ + ret = gpio_request(GPIO_IRQ, "GPIO_133"); + if (ret < 0) { + /*Set Active Low. + * Please reference the file include/linux/interrupt.h*/ + pr_err("sis_ts_probe: Failed to gpio_request\n"); + pr_err("sis_ts_probe: Fail : gpio_request was called before this driver call\n"); + } + /* setting gpio direction here OR boardinfo file*/ + +#else + ret = SIS_ERR; +#endif + return ret; +} + +/*static uint16_t cal_crc_with_cmd(char *data, int start, int end, uint8_t cmd) +{ + int i = 0; + uint16_t crc = 0; + + crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd) & 0x00FF]; + for (i = start; i <= end ; i++) + crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ data[i]) & 0x00FF]; + return crc; +}*/ + +/*static void write_crc(unsigned char *buf, int start, int end) +{ + uint16_t crc = 0; + + crc = cal_crc(buf, start , end); + buf[end+1] = (crc >> 8) & 0xff; + buf[end+2] = crc & 0xff; +}*/ + +#ifdef _STD_RW_IO +#define BUFFER_SIZE MAX_BYTE +static ssize_t sis_cdev_write(struct file *file, const char __user *buf, + size_t count, + loff_t *f_pos) +{ + int ret = 0; + char *kdata; + char cmd; + + pr_info("sis_cdev_write.\n"); + if (ts_bak == 0) + return SIS_ERR_CLIENT; + + ret = access_ok(VERIFY_WRITE, buf, BUFFER_SIZE); + if (!ret) { + pr_err("cannot access user space memory\n"); + return SIS_ERR_ACCESS_USER_MEM; + } + + kdata = kmalloc(BUFFER_SIZE, GFP_KERNEL); + if (kdata == 0) + return SIS_ERR_ALLOCATE_KERNEL_MEM; + + ret = copy_from_user(kdata, buf, BUFFER_SIZE); + if (ret) { + pr_err("copy_from_user fail\n"); + kfree(kdata); + return SIS_ERR_COPY_FROM_USER; + } +#ifdef _DEBUG_PACKAGE + PrintBuffer(0, count, kdata); +#endif + + cmd = kdata[6]; + +/*Write & Read*/ + ret = sis_command_for_write(ts_bak->client, count, kdata); + if (ret < 0) { + pr_err("i2c_transfer write error %d\n", ret); + kfree(kdata); + return SIS_ERR_TRANSMIT_I2C; + } + if (copy_to_user((char *) buf, kdata, BUFFER_SIZE)) { + pr_err("copy_to_user fail\n"); + ret = SIS_ERR_COPY_FROM_KERNEL; + } + kfree(kdata); + return ret; +} + +/*for get system time*/ +static ssize_t sis_cdev_read(struct file *file, char __user *buf, + size_t count, + loff_t *f_pos) +{ + int ret = 0; + char *kdata; + + pr_info("sis_cdev_read.\n"); + if (ts_bak == 0) + return SIS_ERR_CLIENT; + ret = access_ok(VERIFY_WRITE, buf, BUFFER_SIZE); + if (!ret) { + pr_err("cannot access user space memory\n"); + return SIS_ERR_ACCESS_USER_MEM; + } + kdata = kmalloc(BUFFER_SIZE, GFP_KERNEL); + if (kdata == 0) + return SIS_ERR_ALLOCATE_KERNEL_MEM; + ret = copy_from_user(kdata, buf, BUFFER_SIZE); + if (ret) { + pr_err("copy_from_user fail\n"); + kfree(kdata); + return SIS_ERR_COPY_FROM_USER; + } +#ifdef _DEBUG_PACKAGE + PrintBuffer(0, count, kdata); +#endif + /*Write & Read*/ + ret = sis_command_for_read(ts_bak->client, MAX_BYTE, kdata); + if (ret < 0) { + pr_err("i2c_transfer read error %d\n", ret); + kfree(kdata); + return SIS_ERR_TRANSMIT_I2C; + } + + ret = le16_to_cpu(get_unaligned_le16(kdata)); + + /*{ + int i; + + pr_info("ret=%d\n", ret); + for (i = 0; i < ret && i < BUFFER_SIZE; i++) + pr_info("%02x ", kdata[i]); + pr_info("\n"); + }*/ + + if (copy_to_user((char *)buf, kdata, BUFFER_SIZE)) { + pr_err("copy_to_user fail\n"); + ret = SIS_ERR_COPY_FROM_KERNEL; + } + + kfree(kdata); + return ret; +} + +#undef BUFFER_SIZE + +static int sis_cdev_open(struct inode *inode, struct file *filp) +{ + pr_info("sis_cdev_open.\n"); + if (ts_bak == 0) + return SIS_ERR_CLIENT; + + if (ts_bak->use_irq) { + if (!irqd_irq_disabled(&ts_bak->desc->irq_data)) + disable_irq(ts_bak->client->irq); + else { + pr_info("sis_cdev_open: IRQ_STATUS: %x\n", + irqd_irq_disabled(&ts_bak->desc->irq_data)); + } + } + hrtimer_cancel(&ts_bak->timer); + flush_workqueue(sis_wq); /*only flush sis_wq*/ + return 0; /*success*/ +} + +static int sis_cdev_release(struct inode *inode, struct file *filp) +{ + pr_info("sis_cdev_release.\n"); + if (ts_bak == 0) + return SIS_ERR_CLIENT; + if (ts_bak->use_irq) { + if (irqd_irq_disabled(&ts_bak->desc->irq_data)) + enable_irq(ts_bak->client->irq); + } else + hrtimer_start(&ts_bak->timer, ktime_set(1, 0), + HRTIMER_MODE_REL); + return 0; +} + +static const struct file_operations sis_cdev_fops = { + .owner = THIS_MODULE, + .read = sis_cdev_read, + .write = sis_cdev_write, + .open = sis_cdev_open, + .release = sis_cdev_release, +}; + +static int sis_setup_chardev(struct sis_ts_data *ts) +{ + dev_t dev = MKDEV(sis_char_major, 0); + int ret = 0; + struct device *class_dev = NULL; + + pr_info("sis_setup_chardev.\n"); + if (ts == NULL) + return -ENOMEM; + + /*dynamic allocate driver handle*/ + ret = alloc_chrdev_region(&dev, 0, + sis_char_devs_count, DEVICE_NAME); + if (ret) + return ret; + + sis_char_major = MAJOR(dev); + cdev_init(&sis_char_cdev, &sis_cdev_fops); + sis_char_cdev.owner = THIS_MODULE; + ret = cdev_add(&sis_char_cdev, dev, sis_char_devs_count); + if (ret) + goto err1; + + pr_info("%s driver(major %d) installed.\n", + DEVICE_NAME, sis_char_major); + /*register class*/ + sis_char_class = class_create(THIS_MODULE, DEVICE_NAME); + if (IS_ERR(sis_char_class)) { + ret = PTR_ERR(sis_char_class); + goto err2; + } + + class_dev = device_create(sis_char_class, NULL, dev, NULL, DEVICE_NAME); + if (IS_ERR(class_dev)) { + ret = PTR_ERR(class_dev); + goto err3; + } + + return 0; +err3: + class_destroy(sis_char_class); + sis_char_class = NULL; +err2: + cdev_del(&sis_char_cdev); + memset(&sis_char_cdev, 0, sizeof(struct cdev)); +err1: + sis_char_major = 0; + unregister_chrdev_region(dev, sis_char_devs_count); + return ret; +} + +static void sis_deinit_chardev(void) +{ + dev_t dev = MKDEV(sis_char_major, 0); + + if (sis_char_class) { + pr_info("sis_deinit_chardev\n"); + device_destroy(sis_char_class, dev); + class_destroy(sis_char_class); + sis_char_class = NULL; + cdev_del(&sis_char_cdev); + memset(&sis_char_cdev, 0, sizeof(struct cdev)); + sis_char_major = 0; + unregister_chrdev_region(dev, sis_char_devs_count); + } +} +#endif + +static int sis_ts_probe( + struct i2c_client *client, const struct i2c_device_id *id) +{ + int ret = 0; + struct sis_ts_data *ts = NULL; + struct sis_i2c_rmi_platform_data *pdata = NULL; + + pr_info("sis_ts_probe\n"); + TPInfo = kzalloc(sizeof(struct sisTP_driver_data), GFP_KERNEL); + if (TPInfo == NULL) { + ret = -ENOMEM; + goto err_alloc_data_failed; + } + ts = kzalloc(sizeof(struct sis_ts_data), GFP_KERNEL); + if (ts == NULL) { + ret = -ENOMEM; + goto err_alloc_data_failed; + } + ts_bak = ts; + mutex_init(&ts->mutex_wq); + /*1. Init Work queue and necessary buffers*/ + INIT_WORK(&ts->work, sis_ts_work_func); + ts->client = client; + i2c_set_clientdata(client, ts); + pdata = client->dev.platform_data; + if (pdata) + ts->power = pdata->power; + if (ts->power) { + ret = ts->power(1); + if (ret < 0) { + pr_err("sis_ts_probe power on failed\n"); + goto err_power_failed; + } + } + /*2. Allocate input device*/ + ts->input_dev = input_allocate_device(); + if (ts->input_dev == NULL) { + ret = -ENOMEM; + pr_err("sis_ts_probe: Failed to allocate input device\n"); + goto err_input_dev_alloc_failed; + } + /*This input device name should be the same to IDC file name.*/ + ts->input_dev->name = "sis_touch"; + + set_bit(EV_ABS, ts->input_dev->evbit); + set_bit(EV_KEY, ts->input_dev->evbit); + set_bit(ABS_MT_POSITION_X, ts->input_dev->absbit); + set_bit(ABS_MT_POSITION_Y, ts->input_dev->absbit); + set_bit(ABS_MT_TRACKING_ID, ts->input_dev->absbit); + set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); + set_bit(ABS_MT_PRESSURE, ts->input_dev->absbit); + set_bit(ABS_MT_TOUCH_MAJOR, ts->input_dev->absbit); + set_bit(ABS_MT_TOUCH_MINOR, ts->input_dev->absbit); + input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, + 0, PRESSURE_MAX, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, + 0, AREA_LENGTH_LONGER, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MINOR, + 0, AREA_LENGTH_SHORT, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, + 0, SIS_MAX_X, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, + 0, SIS_MAX_Y, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, + 0, 15, 0, 0); + /* add for touch keys */ + set_bit(KEY_COMPOSE, ts->input_dev->keybit); + set_bit(KEY_BACK, ts->input_dev->keybit); + set_bit(KEY_MENU, ts->input_dev->keybit); + set_bit(KEY_HOME, ts->input_dev->keybit); + /*3. Register input device to core*/ + ret = input_register_device(ts->input_dev); + if (ret) { + pr_err("sis_ts_probe: Unable to register %s input device\n", + ts->input_dev->name); + goto err_input_register_device_failed; + } + /*4. irq or timer setup*/ + ret = initial_irq(); + if (ret >= 0) { + client->irq = gpio_to_irq(GPIO_IRQ); + ret = request_irq(client->irq, sis_ts_irq_handler, + IRQF_TRIGGER_FALLING, client->name, ts); + if (ret == 0) + ts->use_irq = 1; + else + dev_err(&client->dev, "request_irq failed\n"); + } + ts->desc = irq_to_desc(ts_bak->client->irq); + hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ts->timer.function = sis_ts_timer_func; + if (!ts->use_irq) + hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); +#ifdef CONFIG_HAS_EARLYSUSPEND + ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + ts->early_suspend.suspend = sis_ts_early_suspend; + ts->early_suspend.resume = sis_ts_late_resume; + register_early_suspend(&ts->early_suspend); +#endif + pr_info("sis_ts_probe: Start touchscreen %s in %s mode\n", + ts->input_dev->name, + ts->use_irq ? "interrupt" : "polling"); + if (ts->use_irq) { +#ifdef _INT_MODE_1 + pr_info("sis_ts_probe: interrupt case 1 mode\n"); +#else + pr_info("sis_ts_probe: interrupt case 2 mode\n"); +#endif + } +#ifdef _STD_RW_IO + ret = sis_setup_chardev(ts); + if (ret) + pr_err("sis_setup_chardev fail\n"); +#endif + pr_info("sis SIS_SLAVE_ADDR: %d\n", SIS_SLAVE_ADDR); + return 0; +err_input_register_device_failed: + input_free_device(ts->input_dev); +err_input_dev_alloc_failed: +err_power_failed: + kfree(ts); +err_alloc_data_failed: + return ret; +} + +static int sis_ts_remove(struct i2c_client *client) +{ + struct sis_ts_data *ts = i2c_get_clientdata(client); +#ifdef CONFIG_HAS_EARLYSUSPEND + unregister_early_suspend(&ts->early_suspend); +#endif +#ifdef _STD_RW_IO + sis_deinit_chardev(); +#endif + if (ts->use_irq) + free_irq(client->irq, ts); + else + hrtimer_cancel(&ts->timer); + input_unregister_device(ts->input_dev); + kfree(ts); + return 0; +} + +static int sis_ts_suspend(struct i2c_client *client, pm_message_t mesg) +{ + int ret = 0; + struct sis_ts_data *ts = i2c_get_clientdata(client); + + TPInfo->pre_keybit_state = 0x0; + + if (ts->use_irq) { + if (!irqd_irq_disabled(&ts->desc->irq_data)) + disable_irq(client->irq); + } else + hrtimer_cancel(&ts->timer); + flush_workqueue(sis_wq); /*only flush sis_wq*/ + + + if (ts->power) { + ret = ts->power(0); + if (ret < 0) + pr_err("sis_ts_suspend power off failed\n"); + } + + return 0; +} + +static int sis_ts_resume(struct i2c_client *client) +{ + int ret = 0; + struct sis_ts_data *ts = i2c_get_clientdata(client); + + if (ts->power) { + ret = ts->power(1); + if (ret < 0) + pr_err("sis_ts_resume power on failed\n"); + } + + if (ts->use_irq) { + if (irqd_irq_disabled(&ts->desc->irq_data)) + enable_irq(client->irq); + } else + hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); + return 0; +} + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void sis_ts_early_suspend(struct early_suspend *h) +{ + struct sis_ts_data *ts; + + TPInfo->pre_keybit_state = 0x0; + ts = container_of(h, struct sis_ts_data, early_suspend); + sis_ts_suspend(ts->client, PMSG_SUSPEND); +} + +static void sis_ts_late_resume(struct early_suspend *h) +{ + struct sis_ts_data *ts; + + ts = container_of(h, struct sis_ts_data, early_suspend); + sis_ts_resume(ts->client); +} +#endif + +#ifdef CONFIG_X86 +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int sis_ts_detect(struct i2c_client *client, + struct i2c_board_info *info) +{ + const char *type_name; + + pr_info("sis_ts_detect\n"); + type_name = "sis_i2c_ts"; + strlcpy(info->type, type_name, I2C_NAME_SIZE); + return 0; +} +#endif + +static const struct i2c_device_id sis_ts_id[] = { + { SIS_I2C_NAME, 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, sis_ts_id); + +static struct i2c_driver sis_ts_driver = { + .probe = sis_ts_probe, + .remove = sis_ts_remove, +#ifndef CONFIG_HAS_EARLYSUSPEND + .suspend = sis_ts_suspend, + .resume = sis_ts_resume, +#endif +#ifdef CONFIG_X86 + .class = I2C_CLASS_HWMON, + .detect = sis_ts_detect, + .address_list = normal_i2c, +#endif + .id_table = sis_ts_id, + .driver = { + .name = SIS_I2C_NAME, + }, +}; + +static int __init sis_ts_init(void) +{ + pr_info("sis_ts_init\n"); + sis_wq = create_singlethread_workqueue("sis_wq"); + + if (!sis_wq) + return -ENOMEM; + return i2c_add_driver(&sis_ts_driver); +} + +static void __exit sis_ts_exit(void) +{ + pr_info("sis_ts_exit\n"); + i2c_del_driver(&sis_ts_driver); + if (sis_wq) + destroy_workqueue(sis_wq); +} + +module_init(sis_ts_init); +module_exit(sis_ts_exit); +MODULE_DESCRIPTION("SiS 9200 Family Touchscreen Driver"); +MODULE_LICENSE("GPL"); diff --git a/linux-3.18.5/drivers/input/touchscreen/sis_i2c.h b/linux-3.18.5/drivers/input/touchscreen/sis_i2c.h new file mode 100644 index 0000000..7639a52 --- /dev/null +++ b/linux-3.18.5/drivers/input/touchscreen/sis_i2c.h @@ -0,0 +1,173 @@ +/* + * include/linux/sis_i2c.h - platform data structure for SiS 9200 family + * + * Copyright (C) 2011 SiS, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Date: 2015/01/15 + * Version: Android_v2.05.00-A639-1113 + */ +#include + +#ifndef _LINUX_SIS_I2C_H +#define _LINUX_SIS_I2C_H + + +#define SIS_I2C_NAME "sis_i2c_ts" +#define SIS_SLAVE_ADDR 0x5c +/*10ms*/ +#define TIMER_NS 10000000 +#define MAX_FINGERS 10 + +/* For standard R/W IO ( SiS firmware application )*/ +#define _STD_RW_IO /*ON/OFF*/ + +/* Check data CRC */ +/*#define _CHECK_CRC*/ /*ON/OFF*/ + +/* Interrupt setting and modes */ +#define _I2C_INT_ENABLE /*ON/OFF*/ +#define GPIO_IRQ 133 + +/* Enable if use interrupt case 1 mode. */ +/* Disable if use interrupt case 2 mode. */ +/*#define _INT_MODE_1*/ /*ON/OFF*/ + +/* Resolution mode */ +/*Constant value*/ +#define SIS_MAX_X 4095 +#define SIS_MAX_Y 4095 + +#define ONE_BYTE 1 +#define FIVE_BYTE 5 +#define EIGHT_BYTE 8 +#define SIXTEEN_BYTE 16 +#define PACKET_BUFFER_SIZE 128 + +#define SIS_CMD_NORMAL 0x0 +#define SIS_CMD_SOFTRESET 0x82 +#define SIS_CMD_RECALIBRATE 0x87 +#define SIS_CMD_POWERMODE 0x90 +#define MSK_TOUCHNUM 0x0f +#define MSK_HAS_CRC 0x10 +#define MSK_DATAFMT 0xe0 +#define MSK_PSTATE 0x0f +#define MSK_PID 0xf0 +#define RES_FMT 0x00 +#define FIX_FMT 0x40 + +/* for new i2c format */ +#define TOUCHDOWN 0x3 +#define TOUCHUP 0x0 +#define MAX_BYTE 64 +#define PRESSURE_MAX 255 + +/*Resolution diagonal */ +#define AREA_LENGTH_LONGER 5792 +/*((SIS_MAX_X^2) + (SIS_MAX_Y^2))^0.5*/ +#define AREA_LENGTH_SHORT 5792 +#define AREA_UNIT (5792/32) + + +#define FORMAT_MODE 1 + +#define MSK_NOBTN 0 +#define MSK_COMP 1 +#define MSK_BACK 2 +#define MSK_MENU 4 +#define MSK_HOME 8 + +#define P_BYTECOUNT 0 +#define ALL_IN_ONE_PACKAGE 0x10 +#define IS_TOUCH(x) (x & 0x1) +#define IS_HIDI2C(x) ((x & 0xF) == 0x06) +#define IS_AREA(x) ((x >> 4) & 0x1) +#define IS_PRESSURE(x) ((x >> 5) & 0x1) +#define IS_SCANTIME(x) ((x >> 6) & 0x1) +/*#define _DEBUG_PACKAGE*/ /*ON/OFF*/ +/*#define _DEBUG_REPORT*/ /*ON/OFF*/ +#define NORMAL_LEN_PER_POINT 6 +#define AREA_LEN_PER_POINT 2 +#define PRESSURE_LEN_PER_POINT 1 + +#define TOUCH_FORMAT 0x1 +#define BUTTON_FORMAT 0x4 +#define HIDI2C_FORMAT 0x6 +#define P_REPORT_ID 2 +#define BUTTON_STATE 3 +#define BUTTON_KEY_COUNT 16 +#define BYTE_BYTECOUNT 2 +#define BYTE_COUNT 1 +#define BYTE_ReportID 1 +#define BYTE_CRC_HIDI2C 0 +#define BYTE_CRC_I2C 2 +#define BYTE_SCANTIME 2 +#define NO_TOUCH_BYTECOUNT 0x3 + +/* TODO */ +#define TOUCH_POWER_PIN 0 +#define TOUCH_RESET_PIN 1 + +/* CMD Define */ +#define BUF_ACK_PLACE_L 4 +#define BUF_ACK_PLACE_H 5 +#define BUF_ACK_L 0xEF +#define BUF_ACK_H 0xBE +#define BUF_NACK_L 0xAD +#define BUF_NACK_H 0xDE +#define BUF_CRC_PLACE 7 + +/* SiS i2c error code */ +#define SIS_ERR -1 +#define SIS_ERR_ACCESS_USER_MEM -11 /* Access user memory fail */ +#define SIS_ERR_ALLOCATE_KERNEL_MEM -12 /* Allocate memory fail */ +#define SIS_ERR_CLIENT -13 /* Client not created */ +#define SIS_ERR_COPY_FROM_USER -14 /* Copy data from user fail */ +#define SIS_ERR_COPY_FROM_KERNEL -19 /* Copy data from kernel fail */ +#define SIS_ERR_TRANSMIT_I2C -21 /* Transmit error in I2C */ + +struct sis_i2c_rmi_platform_data { + int (*power)(int on); /* Only valid in first array entry */ +}; + +struct Point { + int id; + unsigned short x, y; /*uint16_t ?*/ + uint16_t Pressure; + uint16_t Width; + uint16_t Height; +}; + +struct sisTP_driver_data { + int id; + int fingers; + uint8_t pre_keybit_state; + struct Point pt[MAX_FINGERS]; +}; + +struct sis_ts_data { + int (*power)(int on); + int use_irq; + struct i2c_client *client; + struct input_dev *input_dev; + struct hrtimer timer; + struct irq_desc *desc; + struct work_struct work; + struct mutex mutex_wq; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif +}; + +static int sis_ts_suspend(struct i2c_client *client, pm_message_t mesg); +static int sis_ts_resume(struct i2c_client *client); + +#endif /* _LINUX_SIS_I2C_H */ {.n++%ݶw{.n+{G{ayʇڙ,jfhz_(階ݢj"mG?&~iOzv^m ?I From mboxrd@z Thu Jan 1 00:00:00 1970 From: =?UTF-8?B?5pu+5am36JGzICh0YW1teV90c2VuZyk=?= Subject: RE: [PATCH 1/2] INPUT/HID: add touch support for SiS touch driver Date: Thu, 12 Feb 2015 14:07:21 +0800 Message-ID: <8322374EB97AA24A95D0DDBFC8F1CA1DCB07F9@SISMBEV01.sis.com.tw> References: <8322374EB97AA24A95D0DDBFC8F1CA1DBF987B@SISMBEV01.sis.com.tw><1421063449.12454.17.camel@linux-0dmf.site><8322374EB97AA24A95D0DDBFC8F1CA1DBF9DE5@SISMBEV01.sis.com.tw><8322374EB97AA24A95D0DDBFC8F1CA1DBF9E1B@SISMBEV01.sis.com.tw><1421413862.17198.23.camel@linux-0dmf.site> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: base64 Return-path: Content-class: urn:content-classes:message In-Reply-To: Sender: linux-kernel-owner@vger.kernel.org To: Dmitry Torokhov , Oliver Neukum Cc: lkml , linux-input@vger.kernel.org, tammy0524@gmail.com List-Id: linux-input@vger.kernel.org SGksIA0KDQpJJ3ZlIGNoZWNrZWQgdGhlIGNvZGluZyBzdHlsZSBhbmQgbW9kaWZpZWQgdGhlIGky YyBhbmQgaGlkIHRvdWNoIGRyaXZlciBmb3Igc2lzIHRvdWNoIGNvbnRyb2xsZXIuDQpQbGVhc2Ug aGVscCByZXZpZXcgdGhlbS4gDQpUaGFua3MgYSBsb3QuDQoNClRhbW15DQotLS0tLQ0KSGVyZSBp cyB0aGUgc2lzIGkyYyBkcml2ZXIgaW4gaW5wdXQ6DQoNCmxpbnV4LTMuMTguNS9kcml2ZXJzL2lu cHV0L3RvdWNoc2NyZWVuL0tjb25maWcgICB8ICAgIDcgKw0KIGxpbnV4LTMuMTguNS9kcml2ZXJz L2lucHV0L3RvdWNoc2NyZWVuL01ha2VmaWxlICB8ICAgIDEgKw0KIGxpbnV4LTMuMTguNS9kcml2 ZXJzL2lucHV0L3RvdWNoc2NyZWVuL3Npc19pMmMuYyB8IDEwMzIgKysrKysrKysrKysrKysrKysr KysrKw0KIGxpbnV4LTMuMTguNS9kcml2ZXJzL2lucHV0L3RvdWNoc2NyZWVuL3Npc19pMmMuaCB8 ICAxNzMgKysrKw0KIDQgZmlsZXMgY2hhbmdlZCwgMTIxMyBpbnNlcnRpb25zKCspDQoNCg0KLS0t LS0NCmRpZmYgLS1naXQgYS9saW51eC0zLjE4LjUvZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9L Y29uZmlnIGIvbGludXgtMy4xOC41L2RyaXZlcnMvaW5wdXQvdG91Y2hzY3JlZW4vS2NvbmZpZw0K aW5kZXggZTFkODAwMy4uNTA5M2NjYyAxMDA2NDQNCi0tLSBhL2xpbnV4LTMuMTguNS9kcml2ZXJz L2lucHV0L3RvdWNoc2NyZWVuL0tjb25maWcNCisrKyBiL2xpbnV4LTMuMTguNS9kcml2ZXJzL2lu cHV0L3RvdWNoc2NyZWVuL0tjb25maWcNCkBAIC05NjIsNCArOTYyLDExIEBAIGNvbmZpZyBUT1VD SFNDUkVFTl9aRk9SQ0UNCiAJICBUbyBjb21waWxlIHRoaXMgZHJpdmVyIGFzIGEgbW9kdWxlLCBj aG9vc2UgTSBoZXJlOiB0aGUNCiAJICBtb2R1bGUgd2lsbCBiZSBjYWxsZWQgemZvcmNlX3RzLg0K IA0KK2NvbmZpZyBUT1VDSFNDUkVFTl9TSVNfSTJDDQorCXRyaXN0YXRlICJTaVMgOTIwMCBmYW1p bHkgSTJDIHRvdWNoc2NyZWVuIGRyaXZlciINCisJZGVwZW5kcyBvbiBJMkMNCisJZGVmYXVsdCBu DQorCWhlbHANCisJICBUaGlzIGVuYWJsZXMgc3VwcG9ydCBmb3IgU2lTIDkyMDAgZmFtaWx5IG92 ZXIgSTJDIGJhc2VkIHRvdWNoc2NyZWVucy4NCisNCiBlbmRpZg0KZGlmZiAtLWdpdCBhL2xpbnV4 LTMuMTguNS9kcml2ZXJzL2lucHV0L3RvdWNoc2NyZWVuL01ha2VmaWxlIGIvbGludXgtMy4xOC41 L2RyaXZlcnMvaW5wdXQvdG91Y2hzY3JlZW4vTWFrZWZpbGUNCmluZGV4IDA5MGU2MWMuLjI1Y2Zk OWYgMTAwNjQ0DQotLS0gYS9saW51eC0zLjE4LjUvZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9N YWtlZmlsZQ0KKysrIGIvbGludXgtMy4xOC41L2RyaXZlcnMvaW5wdXQvdG91Y2hzY3JlZW4vTWFr ZWZpbGUNCkBAIC03OSwzICs3OSw0IEBAIG9iai0kKENPTkZJR19UT1VDSFNDUkVFTl9XTTk3WFhf WllMT05JVEUpCSs9IHp5bG9uaXRlLXdtOTd4eC5vDQogb2JqLSQoQ09ORklHX1RPVUNIU0NSRUVO X1c5MFg5MDApCSs9IHc5MHA5MTBfdHMubw0KIG9iai0kKENPTkZJR19UT1VDSFNDUkVFTl9UUFM2 NTA3WCkJKz0gdHBzNjUwN3gtdHMubw0KIG9iai0kKENPTkZJR19UT1VDSFNDUkVFTl9aRk9SQ0Up CSs9IHpmb3JjZV90cy5vDQorb2JqLSQoQ09ORklHX1RPVUNIU0NSRUVOX1NJU19JMkMpICAgKz0g c2lzX2kyYy5vDQpkaWZmIC0tZ2l0IGEvbGludXgtMy4xOC41L2RyaXZlcnMvaW5wdXQvdG91Y2hz Y3JlZW4vc2lzX2kyYy5jIGIvbGludXgtMy4xOC41L2RyaXZlcnMvaW5wdXQvdG91Y2hzY3JlZW4v c2lzX2kyYy5jDQpuZXcgZmlsZSBtb2RlIDEwMDY0NA0KaW5kZXggMDAwMDAwMC4uMjYwYTdiNg0K LS0tIC9kZXYvbnVsbA0KKysrIGIvbGludXgtMy4xOC41L2RyaXZlcnMvaW5wdXQvdG91Y2hzY3Jl ZW4vc2lzX2kyYy5jDQpAQCAtMCwwICsxLDEwMzIgQEANCisvKiBkcml2ZXJzL2lucHV0L3RvdWNo c2NyZWVuL3Npc19pMmMuYw0KKyAqICAtIEkyQyBUb3VjaCBwYW5lbCBkcml2ZXIgZm9yIFNpUyA5 MjAwIGZhbWlseQ0KKyAqDQorICogQ29weXJpZ2h0IChDKSAyMDExIFNpUywgSW5jLg0KKyAqDQor ICogVGhpcyBzb2Z0d2FyZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBH ZW5lcmFsIFB1YmxpYw0KKyAqIExpY2Vuc2UgdmVyc2lvbiAyLCBhcyBwdWJsaXNoZWQgYnkgdGhl IEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgYW5kDQorICogbWF5IGJlIGNvcGllZCwgZGlzdHJp YnV0ZWQsIGFuZCBtb2RpZmllZCB1bmRlciB0aG9zZSB0ZXJtcy4NCisgKg0KKyAqIFRoaXMgcHJv Z3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLA0K KyAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdh cnJhbnR5IG9mDQorICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxB UiBQVVJQT1NFLiAgU2VlIHRoZQ0KKyAqIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBt b3JlIGRldGFpbHMuDQorICoNCisgKi8NCisNCisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+DQor I2luY2x1ZGUgPGxpbnV4L2RlbGF5Lmg+DQorI2lmZGVmIENPTkZJR19IQVNfRUFSTFlTVVNQRU5E DQorI2luY2x1ZGUgPGxpbnV4L2Vhcmx5c3VzcGVuZC5oPg0KKyNlbmRpZg0KKyNpbmNsdWRlIDxs aW51eC9ocnRpbWVyLmg+DQorI2luY2x1ZGUgPGxpbnV4L2kyYy5oPg0KKyNpbmNsdWRlIDxsaW51 eC9pbnB1dC5oPg0KKyNpbmNsdWRlIDxsaW51eC9pbnRlcnJ1cHQuaD4NCisjaW5jbHVkZSA8bGlu dXgvaW8uaD4NCisjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+DQorI2luY2x1ZGUg InNpc19pMmMuaCINCisjaW5jbHVkZSA8bGludXgvbGlua2FnZS5oPg0KKyNpbmNsdWRlIDxsaW51 eC9zbGFiLmg+DQorI2luY2x1ZGUgPGxpbnV4L2dwaW8uaD4NCisjaW5jbHVkZSA8bGludXgvdWFj Y2Vzcy5oPg0KKyNpbmNsdWRlIDxsaW51eC9pcnEuaD4NCisjaW5jbHVkZSA8YXNtL3VuYWxpZ25l ZC5oPg0KKw0KKyNpZmRlZiBfU1REX1JXX0lPDQorI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4NCisj aW5jbHVkZSA8bGludXgvZnMuaD4NCisjaW5jbHVkZSA8bGludXgvY2Rldi5oPg0KKyNkZWZpbmUg REVWSUNFX05BTUUgInNpc19hZWdpc190b3VjaF9kZXZpY2UiDQorc3RhdGljIGNvbnN0IGludCBz aXNfY2hhcl9kZXZzX2NvdW50ID0gMTsgICAgICAgIC8qIGRldmljZSBjb3VudCAqLw0KK3N0YXRp YyBpbnQgc2lzX2NoYXJfbWFqb3I7DQorc3RhdGljIHN0cnVjdCBjZGV2IHNpc19jaGFyX2NkZXY7 DQorc3RhdGljIHN0cnVjdCBjbGFzcyAqc2lzX2NoYXJfY2xhc3M7DQorI2VuZGlmDQorDQorLyog QWRkcmVzc2VzIHRvIHNjYW4gKi8NCitzdGF0aWMgY29uc3QgdW5zaWduZWQgc2hvcnQgbm9ybWFs X2kyY1tdID0geyBTSVNfU0xBVkVfQUREUiwgSTJDX0NMSUVOVF9FTkQgfTsNCitzdGF0aWMgc3Ry dWN0IHdvcmtxdWV1ZV9zdHJ1Y3QgKnNpc193cTsNCitzdHJ1Y3Qgc2lzX3RzX2RhdGEgKnRzX2Jh azsNCitzdHJ1Y3Qgc2lzVFBfZHJpdmVyX2RhdGEgKlRQSW5mbzsNCitzdGF0aWMgdm9pZCBzaXNf dHBpbmZvX2NsZWFyKHN0cnVjdCBzaXNUUF9kcml2ZXJfZGF0YSAqVFBJbmZvLCBpbnQgbWF4KTsN CisNCisjaWZkZWYgQ09ORklHX0hBU19FQVJMWVNVU1BFTkQNCitzdGF0aWMgdm9pZCBzaXNfdHNf ZWFybHlfc3VzcGVuZChzdHJ1Y3QgZWFybHlfc3VzcGVuZCAqaCk7DQorc3RhdGljIHZvaWQgc2lz X3RzX2xhdGVfcmVzdW1lKHN0cnVjdCBlYXJseV9zdXNwZW5kICpoKTsNCisjZW5kaWYNCisNCisj aWZkZWYgX0NIRUNLX0NSQw0KK3N0YXRpYyBjb25zdCB1bnNpZ25lZCBzaG9ydCBjcmMxNnRhYlsy NTZdID0gew0KKwkweDAwMDAsIDB4MTAyMSwgMHgyMDQyLCAweDMwNjMsIDB4NDA4NCwgMHg1MGE1 LCAweDYwYzYsIDB4NzBlNywNCisJMHg4MTA4LCAweDkxMjksIDB4YTE0YSwgMHhiMTZiLCAweGMx OGMsIDB4ZDFhZCwgMHhlMWNlLCAweGYxZWYsDQorCTB4MTIzMSwgMHgwMjEwLCAweDMyNzMsIDB4 MjI1MiwgMHg1MmI1LCAweDQyOTQsIDB4NzJmNywgMHg2MmQ2LA0KKwkweDkzMzksIDB4ODMxOCwg MHhiMzdiLCAweGEzNWEsIDB4ZDNiZCwgMHhjMzljLCAweGYzZmYsIDB4ZTNkZSwNCisJMHgyNDYy LCAweDM0NDMsIDB4MDQyMCwgMHgxNDAxLCAweDY0ZTYsIDB4NzRjNywgMHg0NGE0LCAweDU0ODUs DQorCTB4YTU2YSwgMHhiNTRiLCAweDg1MjgsIDB4OTUwOSwgMHhlNWVlLCAweGY1Y2YsIDB4YzVh YywgMHhkNThkLA0KKwkweDM2NTMsIDB4MjY3MiwgMHgxNjExLCAweDA2MzAsIDB4NzZkNywgMHg2 NmY2LCAweDU2OTUsIDB4NDZiNCwNCisJMHhiNzViLCAweGE3N2EsIDB4OTcxOSwgMHg4NzM4LCAw eGY3ZGYsIDB4ZTdmZSwgMHhkNzlkLCAweGM3YmMsDQorCTB4NDhjNCwgMHg1OGU1LCAweDY4ODYs IDB4NzhhNywgMHgwODQwLCAweDE4NjEsIDB4MjgwMiwgMHgzODIzLA0KKwkweGM5Y2MsIDB4ZDll ZCwgMHhlOThlLCAweGY5YWYsIDB4ODk0OCwgMHg5OTY5LCAweGE5MGEsIDB4YjkyYiwNCisJMHg1 YWY1LCAweDRhZDQsIDB4N2FiNywgMHg2YTk2LCAweDFhNzEsIDB4MGE1MCwgMHgzYTMzLCAweDJh MTIsDQorCTB4ZGJmZCwgMHhjYmRjLCAweGZiYmYsIDB4ZWI5ZSwgMHg5Yjc5LCAweDhiNTgsIDB4 YmIzYiwgMHhhYjFhLA0KKwkweDZjYTYsIDB4N2M4NywgMHg0Y2U0LCAweDVjYzUsIDB4MmMyMiwg MHgzYzAzLCAweDBjNjAsIDB4MWM0MSwNCisJMHhlZGFlLCAweGZkOGYsIDB4Y2RlYywgMHhkZGNk LCAweGFkMmEsIDB4YmQwYiwgMHg4ZDY4LCAweDlkNDksDQorCTB4N2U5NywgMHg2ZWI2LCAweDVl ZDUsIDB4NGVmNCwgMHgzZTEzLCAweDJlMzIsIDB4MWU1MSwgMHgwZTcwLA0KKwkweGZmOWYsIDB4 ZWZiZSwgMHhkZmRkLCAweGNmZmMsIDB4YmYxYiwgMHhhZjNhLCAweDlmNTksIDB4OGY3OCwNCisJ MHg5MTg4LCAweDgxYTksIDB4YjFjYSwgMHhhMWViLCAweGQxMGMsIDB4YzEyZCwgMHhmMTRlLCAw eGUxNmYsDQorCTB4MTA4MCwgMHgwMGExLCAweDMwYzIsIDB4MjBlMywgMHg1MDA0LCAweDQwMjUs IDB4NzA0NiwgMHg2MDY3LA0KKwkweDgzYjksIDB4OTM5OCwgMHhhM2ZiLCAweGIzZGEsIDB4YzMz ZCwgMHhkMzFjLCAweGUzN2YsIDB4ZjM1ZSwNCisJMHgwMmIxLCAweDEyOTAsIDB4MjJmMywgMHgz MmQyLCAweDQyMzUsIDB4NTIxNCwgMHg2Mjc3LCAweDcyNTYsDQorCTB4YjVlYSwgMHhhNWNiLCAw eDk1YTgsIDB4ODU4OSwgMHhmNTZlLCAweGU1NGYsIDB4ZDUyYywgMHhjNTBkLA0KKwkweDM0ZTIs IDB4MjRjMywgMHgxNGEwLCAweDA0ODEsIDB4NzQ2NiwgMHg2NDQ3LCAweDU0MjQsIDB4NDQwNSwN CisJMHhhN2RiLCAweGI3ZmEsIDB4ODc5OSwgMHg5N2I4LCAweGU3NWYsIDB4Zjc3ZSwgMHhjNzFk LCAweGQ3M2MsDQorCTB4MjZkMywgMHgzNmYyLCAweDA2OTEsIDB4MTZiMCwgMHg2NjU3LCAweDc2 NzYsIDB4NDYxNSwgMHg1NjM0LA0KKwkweGQ5NGMsIDB4Yzk2ZCwgMHhmOTBlLCAweGU5MmYsIDB4 OTljOCwgMHg4OWU5LCAweGI5OGEsIDB4YTlhYiwNCisJMHg1ODQ0LCAweDQ4NjUsIDB4NzgwNiwg MHg2ODI3LCAweDE4YzAsIDB4MDhlMSwgMHgzODgyLCAweDI4YTMsDQorCTB4Y2I3ZCwgMHhkYjVj LCAweGViM2YsIDB4ZmIxZSwgMHg4YmY5LCAweDliZDgsIDB4YWJiYiwgMHhiYjlhLA0KKwkweDRh NzUsIDB4NWE1NCwgMHg2YTM3LCAweDdhMTYsIDB4MGFmMSwgMHgxYWQwLCAweDJhYjMsIDB4M2E5 MiwNCisJMHhmZDJlLCAweGVkMGYsIDB4ZGQ2YywgMHhjZDRkLCAweGJkYWEsIDB4YWQ4YiwgMHg5 ZGU4LCAweDhkYzksDQorCTB4N2MyNiwgMHg2YzA3LCAweDVjNjQsIDB4NGM0NSwgMHgzY2EyLCAw eDJjODMsIDB4MWNlMCwgMHgwY2MxLA0KKwkweGVmMWYsIDB4ZmYzZSwgMHhjZjVkLCAweGRmN2Ms IDB4YWY5YiwgMHhiZmJhLCAweDhmZDksIDB4OWZmOCwNCisJMHg2ZTE3LCAweDdlMzYsIDB4NGU1 NSwgMHg1ZTc0LCAweDJlOTMsIDB4M2ViMiwgMHgwZWQxLCAweDFlZjANCit9Ow0KKw0KK3N0YXRp YyB1aW50MTZfdCBjYWxfY3JjKGNoYXIgKmNtZCwgaW50IHN0YXJ0LCBpbnQgZW5kKQ0KK3sNCisJ aW50IGkgPSAwOw0KKwl1aW50MTZfdCBjcmMgPSAwOw0KKw0KKwlmb3IgKGkgPSBzdGFydDsgaSA8 PSBlbmQgOyBpKyspDQorCQljcmMgPSAoY3JjIDw8IDgpIF4gY3JjMTZ0YWJbKChjcmMgPj4gOCkg XiBjbWRbaV0pICYgMHgwMEZGXTsNCisJcmV0dXJuIGNyYzsNCit9DQorI2VuZGlmDQorDQorI2lm ZGVmIF9ERUJVR19QQUNLQUdFDQorc3RhdGljIHZvaWQgUHJpbnRCdWZmZXIoaW50IHN0YXJ0LCBp bnQgbGVuZ3RoLCBjaGFyICpidWYpDQorew0KKwlpbnQgaTsNCisNCisJZm9yIChpID0gc3RhcnQ7 IGkgPCBsZW5ndGg7IGkrKykgew0KKwkJcHJfaW5mbygiJTAyeCAiLCBidWZbaV0pOw0KKwkJaWYg KGkgIT0gMCAmJiBpICUgMzAgPT0gMCkNCisJCQlwcl9pbmZvKCJcbiIpOw0KKwl9DQorCXByX2lu Zm8oIlxuIik7DQorfQ0KKyNlbmRpZg0KKw0KK3N0YXRpYyBpbnQgc2lzX2NvbW1hbmRfZm9yX3dy aXRlKHN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQsIGludCB3bGVuZ3RoLA0KKwkJCQkJCQl1bnNp Z25lZCBjaGFyICp3ZGF0YSkNCit7DQorCWludCByZXQgPSBTSVNfRVJSOw0KKwlzdHJ1Y3QgaTJj X21zZyBtc2c7DQorDQorCW1zZy5hZGRyID0gY2xpZW50LT5hZGRyOw0KKwltc2cuZmxhZ3MgPSAw OyAvKldyaXRlKi8NCisJbXNnLmxlbiA9IHdsZW5ndGg7DQorCW1zZy5idWYgPSAodW5zaWduZWQg Y2hhciAqKXdkYXRhOw0KKwlyZXQgPSBpMmNfdHJhbnNmZXIoY2xpZW50LT5hZGFwdGVyLCAmbXNn LCAxKTsNCisJcmV0dXJuIHJldDsNCit9DQorDQorc3RhdGljIGludCBzaXNfY29tbWFuZF9mb3Jf cmVhZChzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50LCBpbnQgcmxlbmd0aCwNCisJCQkJCQkJdW5z aWduZWQgY2hhciAqcmRhdGEpDQorew0KKwlpbnQgcmV0ID0gU0lTX0VSUjsNCisJc3RydWN0IGky Y19tc2cgbXNnOw0KKw0KKwltc2cuYWRkciA9IGNsaWVudC0+YWRkcjsNCisJbXNnLmZsYWdzID0g STJDX01fUkQ7IC8qUmVhZCovDQorCW1zZy5sZW4gPSBybGVuZ3RoOw0KKwltc2cuYnVmID0gcmRh dGE7DQorCXJldCA9IGkyY190cmFuc2ZlcihjbGllbnQtPmFkYXB0ZXIsICZtc2csIDEpOw0KKwly ZXR1cm4gcmV0Ow0KK30NCisNCitzdGF0aWMgaW50IHNpc19jdWxfdW5pdCh1aW50OF90IHJlcG9y dF9pZCkNCit7DQorCWludCByZXQgPSBOT1JNQUxfTEVOX1BFUl9QT0lOVDsNCisNCisJaWYgKHJl cG9ydF9pZCAhPSBBTExfSU5fT05FX1BBQ0tBR0UpIHsNCisJCWlmIChJU19BUkVBKHJlcG9ydF9p ZCkgLyomJiBJU19UT1VDSChyZXBvcnRfaWQpKi8pDQorCQkJcmV0ICs9IEFSRUFfTEVOX1BFUl9Q T0lOVDsNCisJCWlmIChJU19QUkVTU1VSRShyZXBvcnRfaWQpKQ0KKwkJCXJldCArPSBQUkVTU1VS RV9MRU5fUEVSX1BPSU5UOw0KKwl9DQorDQorCXJldHVybiByZXQ7DQorfQ0KKw0KK3N0YXRpYyBp bnQgc2lzX1JlYWRQYWNrZXQoc3RydWN0IGkyY19jbGllbnQgKmNsaWVudCwgdWludDhfdCBjbWQs IHVpbnQ4X3QgKmJ1ZikNCit7DQorCXVpbnQ4X3QgdG1wYnVmW01BWF9CWVRFXSA9IHswfTsJLypN QVhfQllURSA9IDY0OyovDQorCWludCByZXQgPSBTSVNfRVJSOw0KKwlpbnQgdG91Y2hudW0gPSAw Ow0KKwlpbnQgcF9jb3VudCA9IDA7DQorCWludCB0b3VjX2Zvcm1hdGVfaWQgPSAwOw0KKwlpbnQg bG9jYXRlID0gMDsNCisJYm9vbCByZWFkX2ZpcnN0ID0gdHJ1ZTsNCisJLyoNCisJKiBOZXcgaTJj IGZvcm1hdA0KKwkqIGJ1ZlswXSA9IExvdyA4IGJpdHMgb2YgYnl0ZSBjb3VudCB2YWx1ZQ0KKwkq IGJ1ZlsxXSA9IEhpZ2ggOCBiaXRzIG9mIGJ5dGUgY291bnRlIHZhbHVlDQorCSogYnVmWzJdID0g UmVwb3J0IElEDQorCSogYnVmW3RvdWNoIG51bSAqIDYgKyAyIF0gPSBUb3VjaCBpbmZvcm1hdGlv bnM7DQorCSogMSB0b3VjaCBwb2ludCBoYXMgNiBieXRlcywgaXQgY291bGQgYmUgbm9uZSBpZiBu byB0b3VjaA0KKwkqIGJ1Zlt0b3VjaCBudW0gKiA2ICsgM10gPSBUb3VjaCBudW1iZXJzDQorCSoN CisJKiBPbmUgdG91Y2ggcG9pbnQgaW5mb3JtYXRpb24gaW5jbHVkZSA2IGJ5dGVzLCB0aGUgb3Jk ZXIgaXMNCisJKg0KKwkqIDEuIHN0YXR1cyA9IHRvdWNoIGRvd24gb3IgdG91Y2ggdXANCisJKiAy LiBpZCA9IGZpbmdlciBpZA0KKwkqIDMuIHggYXhpcyBsb3cgOCBiaXRzDQorCSogNC4geCBheGlz IGhpZ2ggOCBiaXRzDQorCSogNS4geSBheGlzIGxvdyA4IGJpdHMNCisJKiA2LiB5IGF4aXMgaGln aCA4IGJpdHMNCisJKiAqLw0KKwlkbyB7DQorCQlpZiAobG9jYXRlID49IFBBQ0tFVF9CVUZGRVJf U0laRSkgew0KKwkJCXByX2Vycigic2lzX1JlYWRQYWNrZXQ6IEJ1ZiBPdmVyZmxvd1xuIik7DQor CQkJcmV0dXJuIFNJU19FUlI7DQorCQl9DQorCQlyZXQgPSBzaXNfY29tbWFuZF9mb3JfcmVhZChj bGllbnQsIE1BWF9CWVRFLCB0bXBidWYpOw0KKyNpZmRlZiBfREVCVUdfUEFDS0FHRQ0KKwkJcHJf aW5mbygiY2hhb2JhbiB0ZXN0OiBCdWZfRGF0YSBbMH42M11cbiIpOw0KKwkJUHJpbnRCdWZmZXIo MCwgNjQsIHRtcGJ1Zik7DQorI2VuZGlmDQorCQlpZiAocmV0IDwgMCkgew0KKwkJCXByX2Vycigi c2lzX1JlYWRQYWNrZXQ6IGkyYyB0cmFuc2ZlciBlcnJvclxuIik7DQorCQkJcmV0dXJuIHJldDsN CisJCX0NCisJCS8qZXJyb3IgcGFja2FnZSBsZW5ndGggb2YgcmVjZWl2aW5nIGRhdGEqLw0KKwkJ ZWxzZSBpZiAodG1wYnVmW1BfQllURUNPVU5UXSA+IE1BWF9CWVRFKSB7DQorCQkJcHJfZXJyKCJz aXNfUmVhZFBhY2tldDogRXJyb3IgQnl0ZWNvdW50XG4iKTsNCisJCQlyZXR1cm4gU0lTX0VSUjsN CisJCX0NCisJCWlmIChyZWFkX2ZpcnN0KSB7DQorCQkJLyphY2Nlc3MgTk8gVE9VQ0ggZXZlbnQg dW5sZXNzIEJVVFRPTiBOTyBUT1VDSCBldmVudCovDQorCQkJaWYgKHRtcGJ1ZltQX0JZVEVDT1VO VF0gPT0gMC8qTk9fVE9VQ0hfQllURUNPVU5UKi8pDQorCQkJCXJldHVybiAwOwkvKnRvdWNobnVt IGlzIDAqLw0KKwkJfQ0KKwkJLypza2lwIHBhcnNpbmcgZGF0YSB3aGVuIHR3byBkZXZpY2VzIGFy ZSByZWdpc3RlcmVkDQorCQkgKiBhdCB0aGUgc2FtZSBzbGF2ZSBhZGRyZXNzKi8NCisJCS8qcGFy c2luZyBkYXRhIHdoZW4gUF9SRVBPUlRfSUQgJiYgMHhmIGlzIFRPVUNIX0ZPUk1BVA0KKwkJICog b3IgUF9SRVBPUlRfSUQgaXMgQUxMX0lOX09ORV9QQUNLQUdFKi8NCisJCXRvdWNfZm9ybWF0ZV9p ZCA9IHRtcGJ1ZltQX1JFUE9SVF9JRF0gJiAweGY7DQorCQlpZiAoKHRvdWNfZm9ybWF0ZV9pZCAh PSBUT1VDSF9GT1JNQVQpDQorCQkmJiAodG91Y19mb3JtYXRlX2lkICE9IEhJREkyQ19GT1JNQVQp DQorCQkmJiAodG1wYnVmW1BfUkVQT1JUX0lEXSAhPSBBTExfSU5fT05FX1BBQ0tBR0UpKSB7DQor CQkJcHJfZXJyKCJzaXNfUmVhZFBhY2tldDogRXJyb3IgUmVwb3J0X0lEXG4iKTsNCisJCQlyZXR1 cm4gU0lTX0VSUjsNCisJCX0NCisJCXBfY291bnQgPSAoaW50KSB0bXBidWZbUF9CWVRFQ09VTlRd IC0gMTsJLypzdGFydCBmcm9tIDAqLw0KKwkJaWYgKHRtcGJ1ZltQX1JFUE9SVF9JRF0gIT0gQUxM X0lOX09ORV9QQUNLQUdFKSB7DQorCQkJaWYgKElTX1RPVUNIKHRtcGJ1ZltQX1JFUE9SVF9JRF0p KSB7DQorCQkJCXBfY291bnQgLT0gQllURV9DUkNfSTJDOy8qZGVsZXRlIDIgYnl0ZSBjcmMqLw0K KwkJCX0gZWxzZSBpZiAoSVNfSElESTJDKHRtcGJ1ZltQX1JFUE9SVF9JRF0pKSB7DQorCQkJCXBf Y291bnQgLT0gQllURV9DUkNfSElESTJDOw0KKwkJCX0gZWxzZSB7CS8qc2hvdWxkIG5vdCBiZSBo YXBwZW4qLw0KKwkJCQlwcl9lcnIoInNpc19SZWFkUGFja2V0OiBkZWxldGUgY3JjIGVycm9yXG4i KTsNCisJCQkJcmV0dXJuIFNJU19FUlI7DQorCQkJfQ0KKwkJCWlmIChJU19TQ0FOVElNRSh0bXBi dWZbUF9SRVBPUlRfSURdKSkNCisJCQkJcF9jb3VudCAtPSBCWVRFX1NDQU5USU1FOw0KKwkJfQ0K KwkJLyplbHNlIHt9Ki8gLypGb3IgQUxMX0lOX09ORV9QQUNLQUdFKi8NCisJCWlmIChyZWFkX2Zp cnN0KSB7DQorCQkJdG91Y2hudW0gPSB0bXBidWZbcF9jb3VudF07DQorCQl9IGVsc2Ugew0KKwkJ CWlmICh0bXBidWZbcF9jb3VudF0gIT0gMCkgew0KKwkJCQlwcl9lcnIoInNpc19SZWFkUGFja2V0 OiBnZXQgZXJyb3IgcGFja2FnZVxuIik7DQorCQkJCXJldHVybiBTSVNfRVJSOw0KKwkJCX0NCisJ CX0NCisNCisjaWZkZWYgX0NIRUNLX0NSQw0KKwkJLyogSElEIG92ZXIgSTJDIGRhdGEgZm9yYW10 IGFuZCBubyB0b3VjaCBwYWNrZXQgd2l0aG91dCBDUkMgKi8NCisJCWlmICgodG91Y19mb3JtYXRl X2lkICE9IEhJREkyQ19GT1JNQVQpICYmDQorCQkJKHRtcGJ1ZltQX0JZVEVDT1VOVF0gPiAzKSkg ew0KKwkJCWludCBjcmNfZW5kID0gcF9jb3VudCArIChJU19TQ0FOVElNRSgNCisJCQkJdG1wYnVm W1BfUkVQT1JUX0lEXSkgKiAyKTsNCisJCQl1aW50MTZfdCBidWZfY3JjID0gY2FsX2NyYygNCisJ CQkJdG1wYnVmLCAyLCBjcmNfZW5kKTsvKnN1YiBieXRlY291bnQoMiBieXRlKSovDQorCQkJaW50 IGxfcGFja2FnZV9jcmMgPSAoSVNfU0NBTlRJTUUoDQorCQkJCXRtcGJ1ZltQX1JFUE9SVF9JRF0p ICogMikgKyBwX2NvdW50ICsgMTsNCisJCQl1aW50MTZfdCBwYWNrYWdlX2NyYyA9IGxlMTZfdG9f Y3B1KGdldF91bmFsaWduZWRfbGUxNigNCisJCQkJJnRtcGJ1ZltsX3BhY2thZ2VfY3JjXSkpOw0K Kw0KKwkJCWlmIChidWZfY3JjICE9IHBhY2thZ2VfY3JjKSB7DQorCQkJCXByX2Vycigic2lzX1Jl YWRQYWNrZXQ6IENSQyBFcnJvclxuIik7DQorCQkJCXJldHVybiBTSVNfRVJSOw0KKwkJCX0NCisJ CX0NCisjZW5kaWYNCisJCW1lbWNweSgmYnVmW2xvY2F0ZV0sICZ0bXBidWZbMF0sIDY0KTsNCisJ CS8qQnVmX0RhdGEgWzB+NjNdIFs2NH4xMjhdKi8NCisJCWxvY2F0ZSArPSA2NDsNCisJCXJlYWRf Zmlyc3QgPSBmYWxzZTsNCisJfSB3aGlsZSAodG1wYnVmW1BfUkVQT1JUX0lEXSAhPSBBTExfSU5f T05FX1BBQ0tBR0UgJiYNCisJCQl0bXBidWZbcF9jb3VudF0gPiA1KTsNCisJcmV0dXJuIHRvdWNo bnVtOw0KK30NCisNCisjaWZkZWYgX0lOVF9NT0RFXzENCitzdGF0aWMgdm9pZCB0c19yZXBvcnRf a2V5KHN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQsIHVpbnQ4X3Qga2V5Yml0X3N0YXRlKQ0KK3sN CisJaW50IGkgPSAwOw0KKwl1aW50OF90IGRpZmZfa2V5Yml0X3N0YXRlID0gMHgwOw0KKwkvKmNo ZWNrIGtleWJpdF9zdGF0ZSBpcyBkaWZmZXJlbmNlIHdpdGggcHJlX2tleWJpdF9zdGF0ZSovDQor CXVpbnQ4X3Qga2V5X3ZhbHVlID0gMHgwOyAvKmJ1dHRvbiBsb2NhdGlvbiBmb3IgYmluYXJ5Ki8N CisJdWludDhfdCAga2V5X3ByZXNzZWQgPSAweDA7IC8qYnV0dG9uIGlzIHVwIG9yIGRvd24qLw0K KwlzdHJ1Y3Qgc2lzX3RzX2RhdGEgKnRzID0gaTJjX2dldF9jbGllbnRkYXRhKGNsaWVudCk7DQor DQorCWlmICghdHMpIHsNCisJCXByX2VycigiJXMgZXJyb3I6IE1pc3NpbmcgUGxhdGZvcm0gRGF0 YSFcbiIsIF9fZnVuY19fKTsNCisJCXJldHVybjsNCisJfQ0KKw0KKwlkaWZmX2tleWJpdF9zdGF0 ZSA9IFRQSW5mby0+cHJlX2tleWJpdF9zdGF0ZSBeIGtleWJpdF9zdGF0ZTsNCisNCisJaWYgKGRp ZmZfa2V5Yml0X3N0YXRlKSB7DQorCQlmb3IgKGkgPSAwOyBpIDwgQlVUVE9OX0tFWV9DT1VOVDsg aSsrKSB7DQorCQkJaWYgKChkaWZmX2tleWJpdF9zdGF0ZSA+PiBpKSAmIDB4MDEpIHsNCisJCQkJ a2V5X3ZhbHVlID0gZGlmZl9rZXliaXRfc3RhdGUgJiAoMHgwMSA8PCBpKTsNCisJCQkJa2V5X3By ZXNzZWQgPSAoa2V5Yml0X3N0YXRlID4+IGkpICYgMHgwMTsNCisJCQkJc3dpdGNoIChrZXlfdmFs dWUpIHsNCisJCQkJY2FzZSBNU0tfQ09NUDoNCisJCQkJCWlucHV0X3JlcG9ydF9rZXkodHMtPmlu cHV0X2RldiwNCisJCQkJCQlLRVlfQ09NUE9TRSwga2V5X3ByZXNzZWQpOw0KKwkJCQkJYnJlYWs7 DQorCQkJCWNhc2UgTVNLX0JBQ0s6DQorCQkJCQlpbnB1dF9yZXBvcnRfa2V5KHRzLT5pbnB1dF9k ZXYsDQorCQkJCQkJS0VZX0JBQ0ssIGtleV9wcmVzc2VkKTsNCisJCQkJCWJyZWFrOw0KKwkJCQlj YXNlIE1TS19NRU5VOg0KKwkJCQkJaW5wdXRfcmVwb3J0X2tleSh0cy0+aW5wdXRfZGV2LA0KKwkJ CQkJCUtFWV9NRU5VLCBrZXlfcHJlc3NlZCk7DQorCQkJCQlicmVhazsNCisJCQkJY2FzZSBNU0tf SE9NRToNCisJCQkJCWlucHV0X3JlcG9ydF9rZXkodHMtPmlucHV0X2RldiwNCisJCQkJCQlLRVlf SE9NRSwga2V5X3ByZXNzZWQpOw0KKwkJCQkJYnJlYWs7DQorCQkJCWNhc2UgTVNLX05PQlROOg0K KwkJCQkJLypSZWxlYXNlIHRoZSBidXR0b24gaWYgaXQgdG91Y2hlZC4qLw0KKwkJCQlkZWZhdWx0 Og0KKwkJCQkJYnJlYWs7DQorCQkJCX0NCisJCQl9DQorCQl9DQorCQlUUEluZm8tPnByZV9rZXli aXRfc3RhdGUgPSBrZXliaXRfc3RhdGU7DQorCX0NCit9DQorI2VuZGlmDQorDQorc3RhdGljIHZv aWQgc2lzX3RzX3dvcmtfZnVuYyhzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspDQorew0KKwlzdHJ1 Y3Qgc2lzX3RzX2RhdGEgKnRzID0gY29udGFpbmVyX29mKHdvcmssIHN0cnVjdCBzaXNfdHNfZGF0 YSwgd29yayk7DQorCWludCByZXQgPSBTSVNfRVJSOw0KKwlpbnQgcG9pbnRfdW5pdDsNCisJdWlu dDhfdCBidWZbUEFDS0VUX0JVRkZFUl9TSVpFXSA9IHswfTsNCisJdWludDhfdCBpID0gMCwgZmlu Z2VycyA9IDA7DQorCXVpbnQ4X3QgcHggPSAwLCBweSA9IDAsIHBzdGF0dXMgPSAwOw0KKwl1aW50 OF90IHBfYXJlYSA9IDA7DQorCXVpbnQ4X3QgcF9wcmVhc3VyZSA9IDA7DQorCWJvb2wgYWxsX3Rv dWNoX3VwID0gdHJ1ZTsNCisNCisJbXV0ZXhfbG9jaygmdHMtPm11dGV4X3dxKTsNCisgICAgLyog STJDIG9yIFNNQlVTIGJsb2NrIGRhdGEgcmVhZCAqLw0KKwlyZXQgPSBzaXNfUmVhZFBhY2tldCh0 cy0+Y2xpZW50LCBTSVNfQ01EX05PUk1BTCwgYnVmKTsNCisJLypFcnJvciBOdW1iZXIqLw0KKwlp ZiAocmV0IDwgMCkNCisJCWdvdG8gZXJyX2ZyZWVfYWxsb2NhdGU7DQorCS8qYWNjZXNzIE5PIFRP VUNIIGV2ZW50IHVubGVzcyBCVVRUT04gTk8gVE9VQ0ggZXZlbnQqLw0KKwllbHNlIGlmIChyZXQg PT0gMCkgew0KKwkJZmluZ2VycyA9IDA7DQorCQlzaXNfdHBpbmZvX2NsZWFyKFRQSW5mbywgTUFY X0ZJTkdFUlMpOw0KKwkJZ290byBsYWJlbF9zZW5kX3JlcG9ydDsNCisJCS8qbmVlZCB0byByZXBv cnQgaW5wdXRfbXRfc3luYygpKi8NCisJfQ0KKwlzaXNfdHBpbmZvX2NsZWFyKFRQSW5mbywgTUFY X0ZJTkdFUlMpOw0KKw0KKwkvKlBhcnNlciBhbmQgR2V0IHRoZSBzaXM5MjAwIGRhdGEqLw0KKwlw b2ludF91bml0ID0gc2lzX2N1bF91bml0KGJ1ZltQX1JFUE9SVF9JRF0pOw0KKwlmaW5nZXJzID0g cmV0Ow0KKw0KKwlUUEluZm8tPmZpbmdlcnMgPSBmaW5nZXJzID0gKGZpbmdlcnMgPiBNQVhfRklO R0VSUyA/IDAgOiBmaW5nZXJzKTsNCisNCisJLypmaW5nZXJzIDEwID0gIDAgfiA5Ki8NCisJZm9y IChpID0gMDsgaSA8IGZpbmdlcnM7IGkrKykgew0KKwkJaWYgKChidWZbUF9SRVBPUlRfSURdICE9 IEFMTF9JTl9PTkVfUEFDS0FHRSkgJiYgKGkgPj0gNSkpIHsNCisJCQkvKkNhbGMgcG9pbnQgc3Rh dHVzKi8NCisJCQlwc3RhdHVzID0gQllURV9CWVRFQ09VTlQgKyBCWVRFX1JlcG9ydElEDQorCQkJ CQkrICgoaSAtIDUpICogcG9pbnRfdW5pdCk7DQorCQkJcHN0YXR1cyArPSA2NDsNCisJCX0gZWxz ZSB7DQorCQkJcHN0YXR1cyA9IEJZVEVfQllURUNPVU5UICsgQllURV9SZXBvcnRJRA0KKwkJCQkJ KyAoaSAqIHBvaW50X3VuaXQpOw0KKwkJCQkJLypDYWxjIHBvaW50IHN0YXR1cyovDQorCQl9DQor CSAgICBweCA9IHBzdGF0dXMgKyAyOwkvKkNhbGMgcG9pbnQgeF9jb29yZCovDQorCSAgICBweSA9 IHB4ICsgMjsJLypDYWxjIHBvaW50IHlfY29vcmQqLw0KKwkJaWYgKChidWZbcHN0YXR1c10pID09 IFRPVUNIVVApIHsNCisJCQlUUEluZm8tPnB0W2ldLldpZHRoID0gMDsNCisJCQlUUEluZm8tPnB0 W2ldLkhlaWdodCA9IDA7DQorCQkJVFBJbmZvLT5wdFtpXS5QcmVzc3VyZSA9IDA7DQorCQl9IGVs c2UgaWYgKGJ1ZltQX1JFUE9SVF9JRF0gPT0gQUxMX0lOX09ORV9QQUNLQUdFDQorCQkJCQkmJiAo YnVmW3BzdGF0dXNdKSA9PSBUT1VDSERPV04pIHsNCisJCQlUUEluZm8tPnB0W2ldLldpZHRoID0g MTsNCisJCQlUUEluZm8tPnB0W2ldLkhlaWdodCA9IDE7DQorCQkJVFBJbmZvLT5wdFtpXS5QcmVz c3VyZSA9IDE7DQorCQl9IGVsc2UgaWYgKChidWZbcHN0YXR1c10pID09IFRPVUNIRE9XTikgew0K KwkJCXBfYXJlYSA9IHB5ICsgMjsNCisJCQlwX3ByZWFzdXJlID0gcHkgKyAyICsgKElTX0FSRUEo YnVmW1BfUkVQT1JUX0lEXSkgKiAyKTsNCisJCQkvKmFyZWEqLw0KKwkJCWlmIChJU19BUkVBKGJ1 ZltQX1JFUE9SVF9JRF0pKSB7DQorCQkJCVRQSW5mby0+cHRbaV0uV2lkdGggPSBidWZbcF9hcmVh XTsNCisJCQkJVFBJbmZvLT5wdFtpXS5IZWlnaHQgPSBidWZbcF9hcmVhICsgMV07DQorCQkJfSBl bHNlIHsNCisJCQkJVFBJbmZvLT5wdFtpXS5XaWR0aCA9IDE7DQorCQkJCVRQSW5mby0+cHRbaV0u SGVpZ2h0ID0gMTsNCisJCQl9DQorCQkJLypwcmVhc3VyZSovDQorCQkJaWYgKElTX1BSRVNTVVJF KGJ1ZltQX1JFUE9SVF9JRF0pKQ0KKwkJCQlUUEluZm8tPnB0W2ldLlByZXNzdXJlID0gKGJ1Zltw X3ByZWFzdXJlXSk7DQorCQkJZWxzZQ0KKwkJCQlUUEluZm8tPnB0W2ldLlByZXNzdXJlID0gMTsN CisJCX0gZWxzZSB7DQorCQkJcHJfZXJyKCJzaXNfdHNfd29ya19mdW5jOiBFcnJvciBUb3VjaCBT dGF0dXNcbiIpOw0KKwkJCWdvdG8gZXJyX2ZyZWVfYWxsb2NhdGU7DQorCQl9DQorCQlUUEluZm8t PnB0W2ldLmlkID0gKGJ1Zltwc3RhdHVzICsgMV0pOw0KKwkJVFBJbmZvLT5wdFtpXS54ID0gbGUx Nl90b19jcHUoZ2V0X3VuYWxpZ25lZF9sZTE2KCZidWZbcHhdKSk7DQorCQlUUEluZm8tPnB0W2ld LnkgPSBsZTE2X3RvX2NwdShnZXRfdW5hbGlnbmVkX2xlMTYoJmJ1ZltweV0pKTsNCisJfQ0KKw0K KyNpZmRlZiBfREVCVUdfUkVQT1JUDQorCWZvciAoaSA9IDA7IGkgPCBUUEluZm8tPmZpbmdlcnM7 IGkrKykNCisJCXByX2luZm8oImNoYW9iYW4gdGVzdDogaSA9ICVkLCBpZCA9ICVkLCB4ID0gJWQs IHkgPSAlZCwgcHN0YXR1cyA9ICVkLCB3aWR0aCA9ICVkLCBoZWlnaHQgPSAlZCwgcHJlc3N1cmUg PSAlZFxuIiwNCisJCWksIFRQSW5mby0+cHRbaV0uaWQsIFRQSW5mby0+cHRbaV0ueCwgVFBJbmZv LT5wdFtpXS55LA0KKwkJYnVmW3BzdGF0dXNdLCBUUEluZm8tPnB0W2ldLldpZHRoLCBUUEluZm8t PnB0W2ldLkhlaWdodCwNCisJCVRQSW5mby0+cHRbaV0uUHJlc3N1cmUpOw0KKyNlbmRpZg0KK2xh YmVsX3NlbmRfcmVwb3J0Og0KKy8qIFJlcG9ydCBjby1vcmRpbmF0ZXMgdG8gdGhlIG11bHRpLXRv dWNoIHN0YWNrICovDQorCWZvciAoaSA9IDA7ICgoaSA8IFRQSW5mby0+ZmluZ2VycykgJiYgKGkg PCBNQVhfRklOR0VSUykpOyBpKyspIHsNCisJCWlmIChUUEluZm8tPnB0W2ldLlByZXNzdXJlKSB7 DQorCQkJVFBJbmZvLT5wdFtpXS5XaWR0aCAqPSBBUkVBX1VOSVQ7DQorCQkJaW5wdXRfcmVwb3J0 X2Ficyh0cy0+aW5wdXRfZGV2LCBBQlNfTVRfVE9VQ0hfTUFKT1IsDQorCQkJCQkJCVRQSW5mby0+ cHRbaV0uV2lkdGgpOw0KKwkJCVRQSW5mby0+cHRbaV0uSGVpZ2h0ICo9IEFSRUFfVU5JVDsNCisJ CQlpbnB1dF9yZXBvcnRfYWJzKHRzLT5pbnB1dF9kZXYsIEFCU19NVF9UT1VDSF9NSU5PUiwNCisJ CQkJCQkJVFBJbmZvLT5wdFtpXS5IZWlnaHQpOw0KKwkJCWlucHV0X3JlcG9ydF9hYnModHMtPmlu cHV0X2RldiwgQUJTX01UX1BSRVNTVVJFLA0KKwkJCQkJCQlUUEluZm8tPnB0W2ldLlByZXNzdXJl KTsNCisJCQlpbnB1dF9yZXBvcnRfYWJzKHRzLT5pbnB1dF9kZXYsIEFCU19NVF9QT1NJVElPTl9Y LA0KKwkJCQkJCQlUUEluZm8tPnB0W2ldLngpOw0KKwkJCWlucHV0X3JlcG9ydF9hYnModHMtPmlu cHV0X2RldiwgQUJTX01UX1BPU0lUSU9OX1ksDQorCQkJCQkJCVRQSW5mby0+cHRbaV0ueSk7DQor CQkJaW5wdXRfcmVwb3J0X2Ficyh0cy0+aW5wdXRfZGV2LCBBQlNfTVRfVFJBQ0tJTkdfSUQsDQor CQkJCQkJCVRQSW5mby0+cHRbaV0uaWQpOw0KKwkJCS8qQW5kcm9pZCAyLjMqLw0KKwkJCWlucHV0 X210X3N5bmModHMtPmlucHV0X2Rldik7DQorCQkJYWxsX3RvdWNoX3VwID0gZmFsc2U7DQorCQl9 DQorCQlpZiAoaSA9PSAoVFBJbmZvLT5maW5nZXJzIC0gMSkgJiYgYWxsX3RvdWNoX3VwID09IHRy dWUpDQorCQkJaW5wdXRfbXRfc3luYyh0cy0+aW5wdXRfZGV2KTsNCisJfQ0KKwlpZiAoVFBJbmZv LT5maW5nZXJzID09IDApDQorCQlpbnB1dF9tdF9zeW5jKHRzLT5pbnB1dF9kZXYpOw0KKwlpbnB1 dF9zeW5jKHRzLT5pbnB1dF9kZXYpOw0KKw0KK2Vycl9mcmVlX2FsbG9jYXRlOg0KKw0KKwlpZiAo dHMtPnVzZV9pcnEpIHsNCisjaWZkZWYgX0lOVF9NT0RFXzEJLypjYXNlIDEgbW9kZSovDQorCQkv KlRPRE86IEFmdGVyIGludGVycnVwdCBzdGF0dXMgbG93LA0KKwkJICogcmVhZCBpMmMgYnVzIGRh dGEgYnkgcG9sbGluZywNCisJCSAqIHVudGlsIGludGVycnVwdCBzdGF0dXMgaXMgaGlnaCovDQor CQlyZXQgPSAgZ3Bpb19nZXRfdmFsdWUoR1BJT19JUlEpOw0KKwkJLyppbnRlcnJ1cHQgcGluIGlz IHN0aWxsIExPVywNCisJCSAqIHJlYWQgZGF0YSB1bnRpbCBpbnRlcnJ1cHQgcGluIGlzIHJlbGVh c2VkLiovDQorCQlpZiAoIXJldCkNCisJCQlocnRpbWVyX3N0YXJ0KCZ0cy0+dGltZXIsIGt0aW1l X3NldCgwLCBUSU1FUl9OUyksDQorCQkJCQkJSFJUSU1FUl9NT0RFX1JFTCk7DQorCQllbHNlIHsN CisJCQlpZiAoVFBJbmZvLT5wcmVfa2V5Yml0X3N0YXRlKQ0KKwkJCQkvKmNsZWFyIGZvciBpbnRl cnJ1cHQqLw0KKwkJCQl0c19yZXBvcnRfa2V5KHRzLT5jbGllbnQsIDB4MCk7DQorDQorCQkJaWYg KGlycWRfaXJxX2Rpc2FibGVkKCZ0cy0+ZGVzYy0+aXJxX2RhdGEpKQ0KKwkJCQllbmFibGVfaXJx KHRzLT5jbGllbnQtPmlycSk7DQorCQl9DQorI2Vsc2UgLypjYXNlIDIgbW9kZSovDQorCQlpZiAo aXJxZF9pcnFfZGlzYWJsZWQoJnRzLT5kZXNjLT5pcnFfZGF0YSkpDQorCQkJZW5hYmxlX2lycSh0 cy0+Y2xpZW50LT5pcnEpOw0KKyNlbmRpZg0KKwl9DQorDQorCW11dGV4X3VubG9jaygmdHMtPm11 dGV4X3dxKTsNCit9DQorDQorc3RhdGljIHZvaWQgc2lzX3RwaW5mb19jbGVhcihzdHJ1Y3Qgc2lz VFBfZHJpdmVyX2RhdGEgKlRQSW5mbywgaW50IG1heCkNCit7DQorCWludCBpID0gMDsNCisNCisJ Zm9yIChpID0gMDsgaSA8IG1heDsgaSsrKSB7DQorCQlUUEluZm8tPnB0W2ldLmlkID0gLTE7DQor CQlUUEluZm8tPnB0W2ldLnggPSAwOw0KKwkJVFBJbmZvLT5wdFtpXS55ID0gMDsNCisJCVRQSW5m by0+cHRbaV0uUHJlc3N1cmUgPSAwOw0KKwkJVFBJbmZvLT5wdFtpXS5XaWR0aCA9IDA7DQorCX0N CisJVFBJbmZvLT5pZCA9IDB4MDsNCisJVFBJbmZvLT5maW5nZXJzID0gMDsNCit9DQorDQorc3Rh dGljIGVudW0gaHJ0aW1lcl9yZXN0YXJ0IHNpc190c190aW1lcl9mdW5jKHN0cnVjdCBocnRpbWVy ICp0aW1lcikNCit7DQorCXN0cnVjdCBzaXNfdHNfZGF0YSAqdHMgPSBjb250YWluZXJfb2YodGlt ZXIsIHN0cnVjdCBzaXNfdHNfZGF0YSwgdGltZXIpOw0KKw0KKwlxdWV1ZV93b3JrKHNpc193cSwg JnRzLT53b3JrKTsNCisJaWYgKCF0cy0+dXNlX2lycSkJLypGb3IgUG9sbGluZyBtb2RlKi8NCisJ ICAgIGhydGltZXJfc3RhcnQoJnRzLT50aW1lciwga3RpbWVfc2V0KDAsIFRJTUVSX05TKSwgSFJU SU1FUl9NT0RFX1JFTCk7DQorCXJldHVybiBIUlRJTUVSX05PUkVTVEFSVDsNCit9DQorDQorc3Rh dGljIGlycXJldHVybl90IHNpc190c19pcnFfaGFuZGxlcihpbnQgaXJxLCB2b2lkICpkZXZfaWQp DQorew0KKwlzdHJ1Y3Qgc2lzX3RzX2RhdGEgKnRzID0gZGV2X2lkOw0KKw0KKwlpZiAoIWlycWRf aXJxX2Rpc2FibGVkKCZ0cy0+ZGVzYy0+aXJxX2RhdGEpKQ0KKwkJZGlzYWJsZV9pcnFfbm9zeW5j KHRzLT5jbGllbnQtPmlycSk7DQorCXF1ZXVlX3dvcmsoc2lzX3dxLCAmdHMtPndvcmspOw0KKwly ZXR1cm4gSVJRX0hBTkRMRUQ7DQorfQ0KKw0KK3N0YXRpYyBpbnQgaW5pdGlhbF9pcnEodm9pZCkN Cit7DQorCWludCByZXQgPSAwOw0KKyNpZmRlZiBfSTJDX0lOVF9FTkFCTEUNCisJLyogaW5pdGlh bGl6ZSBncGlvIGFuZCBpbnRlcnJ1cHQgcGlucyAqLw0KKwkvKmV4LiBHUElPXzEzMyBmb3IgaW50 ZXJydXB0IG1vZGUqLw0KKwlyZXQgPSBncGlvX3JlcXVlc3QoR1BJT19JUlEsICJHUElPXzEzMyIp Ow0KKwlpZiAocmV0IDwgMCkgew0KKwkJLypTZXQgQWN0aXZlIExvdy4NCisJCSAqIFBsZWFzZSBy ZWZlcmVuY2UgdGhlIGZpbGUgaW5jbHVkZS9saW51eC9pbnRlcnJ1cHQuaCovDQorCQlwcl9lcnIo InNpc190c19wcm9iZTogRmFpbGVkIHRvIGdwaW9fcmVxdWVzdFxuIik7DQorCQlwcl9lcnIoInNp c190c19wcm9iZTogRmFpbCA6IGdwaW9fcmVxdWVzdCB3YXMgY2FsbGVkIGJlZm9yZSB0aGlzIGRy aXZlciBjYWxsXG4iKTsNCisJfQ0KKwkvKiBzZXR0aW5nIGdwaW8gZGlyZWN0aW9uIGhlcmUgT1Ig Ym9hcmRpbmZvIGZpbGUqLw0KKw0KKyNlbHNlDQorCXJldCA9IFNJU19FUlI7DQorI2VuZGlmDQor CXJldHVybiByZXQ7DQorfQ0KKw0KKy8qc3RhdGljIHVpbnQxNl90IGNhbF9jcmNfd2l0aF9jbWQo Y2hhciAqZGF0YSwgaW50IHN0YXJ0LCBpbnQgZW5kLCB1aW50OF90IGNtZCkNCit7DQorCWludCBp ID0gMDsNCisJdWludDE2X3QgY3JjID0gMDsNCisNCisJY3JjID0gKGNyYyA8PCA4KSBeIGNyYzE2 dGFiWygoY3JjID4+IDgpIF4gY21kKSAmIDB4MDBGRl07DQorCWZvciAoaSA9IHN0YXJ0OyBpIDw9 IGVuZCA7IGkrKykNCisJCWNyYyA9IChjcmMgPDwgOCkgXiBjcmMxNnRhYlsoKGNyYyA+PiA4KSBe IGRhdGFbaV0pICYgMHgwMEZGXTsNCisJcmV0dXJuIGNyYzsNCit9Ki8NCisNCisvKnN0YXRpYyB2 b2lkIHdyaXRlX2NyYyh1bnNpZ25lZCBjaGFyICpidWYsIGludCBzdGFydCwgaW50IGVuZCkNCit7 DQorCXVpbnQxNl90IGNyYyA9IDA7DQorDQorCWNyYyA9IGNhbF9jcmMoYnVmLCBzdGFydCAsIGVu ZCk7DQorCWJ1ZltlbmQrMV0gPSAoY3JjID4+IDgpICYgMHhmZjsNCisJYnVmW2VuZCsyXSA9IGNy YyAmIDB4ZmY7DQorfSovDQorDQorI2lmZGVmIF9TVERfUldfSU8NCisjZGVmaW5lIEJVRkZFUl9T SVpFIE1BWF9CWVRFDQorc3RhdGljIHNzaXplX3Qgc2lzX2NkZXZfd3JpdGUoc3RydWN0IGZpbGUg KmZpbGUsIGNvbnN0IGNoYXIgX191c2VyICpidWYsDQorCQkJCQkJCQlzaXplX3QgY291bnQsDQor CQkJCQkJCQlsb2ZmX3QgKmZfcG9zKQ0KK3sNCisJaW50IHJldCA9IDA7DQorCWNoYXIgKmtkYXRh Ow0KKwljaGFyIGNtZDsNCisNCisJcHJfaW5mbygic2lzX2NkZXZfd3JpdGUuXG4iKTsNCisJaWYg KHRzX2JhayA9PSAwKQ0KKwkJcmV0dXJuIFNJU19FUlJfQ0xJRU5UOw0KKw0KKwlyZXQgPSBhY2Nl c3Nfb2soVkVSSUZZX1dSSVRFLCBidWYsIEJVRkZFUl9TSVpFKTsNCisJaWYgKCFyZXQpIHsNCisJ CXByX2VycigiY2Fubm90IGFjY2VzcyB1c2VyIHNwYWNlIG1lbW9yeVxuIik7DQorCQlyZXR1cm4g U0lTX0VSUl9BQ0NFU1NfVVNFUl9NRU07DQorCX0NCisNCisJa2RhdGEgPSBrbWFsbG9jKEJVRkZF Ul9TSVpFLCBHRlBfS0VSTkVMKTsNCisJaWYgKGtkYXRhID09IDApDQorCQlyZXR1cm4gU0lTX0VS Ul9BTExPQ0FURV9LRVJORUxfTUVNOw0KKw0KKwlyZXQgPSBjb3B5X2Zyb21fdXNlcihrZGF0YSwg YnVmLCBCVUZGRVJfU0laRSk7DQorCWlmIChyZXQpIHsNCisJCXByX2VycigiY29weV9mcm9tX3Vz ZXIgZmFpbFxuIik7DQorCQlrZnJlZShrZGF0YSk7DQorCQlyZXR1cm4gU0lTX0VSUl9DT1BZX0ZS T01fVVNFUjsNCisJfQ0KKyNpZmRlZiBfREVCVUdfUEFDS0FHRQ0KKwlQcmludEJ1ZmZlcigwLCBj b3VudCwga2RhdGEpOw0KKyNlbmRpZg0KKw0KKwljbWQgPSBrZGF0YVs2XTsNCisNCisvKldyaXRl ICYgUmVhZCovDQorCXJldCA9IHNpc19jb21tYW5kX2Zvcl93cml0ZSh0c19iYWstPmNsaWVudCwg Y291bnQsIGtkYXRhKTsNCisJaWYgKHJldCA8IDApIHsNCisJCXByX2VycigiaTJjX3RyYW5zZmVy IHdyaXRlIGVycm9yICVkXG4iLCByZXQpOw0KKwkJa2ZyZWUoa2RhdGEpOw0KKwkJcmV0dXJuIFNJ U19FUlJfVFJBTlNNSVRfSTJDOw0KKwl9DQorCWlmIChjb3B5X3RvX3VzZXIoKGNoYXIgKikgYnVm LCBrZGF0YSwgQlVGRkVSX1NJWkUpKSB7DQorCQlwcl9lcnIoImNvcHlfdG9fdXNlciBmYWlsXG4i KTsNCisJCXJldCA9IFNJU19FUlJfQ09QWV9GUk9NX0tFUk5FTDsNCisJfQ0KKwlrZnJlZShrZGF0 YSk7DQorCXJldHVybiByZXQ7DQorfQ0KKw0KKy8qZm9yIGdldCBzeXN0ZW0gdGltZSovDQorc3Rh dGljIHNzaXplX3Qgc2lzX2NkZXZfcmVhZChzdHJ1Y3QgZmlsZSAqZmlsZSwgY2hhciBfX3VzZXIg KmJ1ZiwNCisJCQkJCQkJCXNpemVfdCBjb3VudCwNCisJCQkJCQkJCWxvZmZfdCAqZl9wb3MpDQor ew0KKwlpbnQgcmV0ID0gMDsNCisJY2hhciAqa2RhdGE7DQorDQorCXByX2luZm8oInNpc19jZGV2 X3JlYWQuXG4iKTsNCisJaWYgKHRzX2JhayA9PSAwKQ0KKwkJcmV0dXJuIFNJU19FUlJfQ0xJRU5U Ow0KKwlyZXQgPSBhY2Nlc3Nfb2soVkVSSUZZX1dSSVRFLCBidWYsIEJVRkZFUl9TSVpFKTsNCisJ aWYgKCFyZXQpIHsNCisJCXByX2VycigiY2Fubm90IGFjY2VzcyB1c2VyIHNwYWNlIG1lbW9yeVxu Iik7DQorCQlyZXR1cm4gU0lTX0VSUl9BQ0NFU1NfVVNFUl9NRU07DQorCX0NCisJa2RhdGEgPSBr bWFsbG9jKEJVRkZFUl9TSVpFLCBHRlBfS0VSTkVMKTsNCisJaWYgKGtkYXRhID09IDApDQorCQly ZXR1cm4gU0lTX0VSUl9BTExPQ0FURV9LRVJORUxfTUVNOw0KKwlyZXQgPSBjb3B5X2Zyb21fdXNl cihrZGF0YSwgYnVmLCBCVUZGRVJfU0laRSk7DQorCWlmIChyZXQpIHsNCisJCXByX2VycigiY29w eV9mcm9tX3VzZXIgZmFpbFxuIik7DQorCQlrZnJlZShrZGF0YSk7DQorCQlyZXR1cm4gU0lTX0VS Ul9DT1BZX0ZST01fVVNFUjsNCisJfQ0KKyNpZmRlZiBfREVCVUdfUEFDS0FHRQ0KKwlQcmludEJ1 ZmZlcigwLCBjb3VudCwga2RhdGEpOw0KKyNlbmRpZg0KKwkvKldyaXRlICYgUmVhZCovDQorCXJl dCA9IHNpc19jb21tYW5kX2Zvcl9yZWFkKHRzX2Jhay0+Y2xpZW50LCBNQVhfQllURSwga2RhdGEp Ow0KKwlpZiAocmV0IDwgMCkgew0KKwkJcHJfZXJyKCJpMmNfdHJhbnNmZXIgcmVhZCBlcnJvciAl ZFxuIiwgcmV0KTsNCisJCWtmcmVlKGtkYXRhKTsNCisJCXJldHVybiBTSVNfRVJSX1RSQU5TTUlU X0kyQzsNCisJfQ0KKw0KKwlyZXQgPSBsZTE2X3RvX2NwdShnZXRfdW5hbGlnbmVkX2xlMTYoa2Rh dGEpKTsNCisNCisJLyp7DQorCQlpbnQgaTsNCisNCisJCXByX2luZm8oInJldD0lZFxuIiwgcmV0 KTsNCisJCWZvciAoaSA9IDA7IGkgPCByZXQgJiYgaSA8IEJVRkZFUl9TSVpFOyBpKyspDQorCQkJ cHJfaW5mbygiJTAyeCAiLCBrZGF0YVtpXSk7DQorCQlwcl9pbmZvKCJcbiIpOw0KKwl9Ki8NCisN CisJaWYgKGNvcHlfdG9fdXNlcigoY2hhciAqKWJ1Ziwga2RhdGEsIEJVRkZFUl9TSVpFKSkgew0K KwkJcHJfZXJyKCJjb3B5X3RvX3VzZXIgZmFpbFxuIik7DQorCQlyZXQgPSBTSVNfRVJSX0NPUFlf RlJPTV9LRVJORUw7DQorCX0NCisNCisJa2ZyZWUoa2RhdGEpOw0KKwlyZXR1cm4gcmV0Ow0KK30N CisNCisjdW5kZWYgQlVGRkVSX1NJWkUNCisNCitzdGF0aWMgaW50IHNpc19jZGV2X29wZW4oc3Ry dWN0IGlub2RlICppbm9kZSwgc3RydWN0IGZpbGUgKmZpbHApDQorew0KKwlwcl9pbmZvKCJzaXNf Y2Rldl9vcGVuLlxuIik7DQorCWlmICh0c19iYWsgPT0gMCkNCisJCXJldHVybiBTSVNfRVJSX0NM SUVOVDsNCisNCisJaWYgKHRzX2Jhay0+dXNlX2lycSkgew0KKwkJaWYgKCFpcnFkX2lycV9kaXNh YmxlZCgmdHNfYmFrLT5kZXNjLT5pcnFfZGF0YSkpDQorCQkJZGlzYWJsZV9pcnEodHNfYmFrLT5j bGllbnQtPmlycSk7DQorCQllbHNlIHsNCisJCQlwcl9pbmZvKCJzaXNfY2Rldl9vcGVuOiBJUlFf U1RBVFVTOiAleFxuIiwNCisJCQlpcnFkX2lycV9kaXNhYmxlZCgmdHNfYmFrLT5kZXNjLT5pcnFf ZGF0YSkpOw0KKwkJfQ0KKwl9DQorCWhydGltZXJfY2FuY2VsKCZ0c19iYWstPnRpbWVyKTsNCisJ Zmx1c2hfd29ya3F1ZXVlKHNpc193cSk7CQkvKm9ubHkgZmx1c2ggc2lzX3dxKi8NCisJcmV0dXJu IDA7CS8qc3VjY2VzcyovDQorfQ0KKw0KK3N0YXRpYyBpbnQgc2lzX2NkZXZfcmVsZWFzZShzdHJ1 Y3QgaW5vZGUgKmlub2RlLCBzdHJ1Y3QgZmlsZSAqZmlscCkNCit7DQorCXByX2luZm8oInNpc19j ZGV2X3JlbGVhc2UuXG4iKTsNCisJaWYgKHRzX2JhayA9PSAwKQ0KKwkJcmV0dXJuIFNJU19FUlJf Q0xJRU5UOw0KKwlpZiAodHNfYmFrLT51c2VfaXJxKSB7DQorCQlpZiAoaXJxZF9pcnFfZGlzYWJs ZWQoJnRzX2Jhay0+ZGVzYy0+aXJxX2RhdGEpKQ0KKwkJCWVuYWJsZV9pcnEodHNfYmFrLT5jbGll bnQtPmlycSk7DQorCX0gZWxzZQ0KKwkJaHJ0aW1lcl9zdGFydCgmdHNfYmFrLT50aW1lciwga3Rp bWVfc2V0KDEsIDApLA0KKwkJCQkJSFJUSU1FUl9NT0RFX1JFTCk7DQorCXJldHVybiAwOw0KK30N CisNCitzdGF0aWMgY29uc3Qgc3RydWN0IGZpbGVfb3BlcmF0aW9ucyBzaXNfY2Rldl9mb3BzID0g ew0KKwkub3duZXIJPSBUSElTX01PRFVMRSwNCisJLnJlYWQJPSBzaXNfY2Rldl9yZWFkLA0KKwku d3JpdGUJPSBzaXNfY2Rldl93cml0ZSwNCisJLm9wZW4JPSBzaXNfY2Rldl9vcGVuLA0KKwkucmVs ZWFzZQk9IHNpc19jZGV2X3JlbGVhc2UsDQorfTsNCisNCitzdGF0aWMgaW50IHNpc19zZXR1cF9j aGFyZGV2KHN0cnVjdCBzaXNfdHNfZGF0YSAqdHMpDQorew0KKwlkZXZfdCBkZXYgPSBNS0RFVihz aXNfY2hhcl9tYWpvciwgMCk7DQorCWludCByZXQgPSAwOw0KKwlzdHJ1Y3QgZGV2aWNlICpjbGFz c19kZXYgPSBOVUxMOw0KKw0KKwlwcl9pbmZvKCJzaXNfc2V0dXBfY2hhcmRldi5cbiIpOw0KKwlp ZiAodHMgPT0gTlVMTCkNCisJCXJldHVybiAtRU5PTUVNOw0KKw0KKwkvKmR5bmFtaWMgYWxsb2Nh dGUgZHJpdmVyIGhhbmRsZSovDQorCXJldCA9IGFsbG9jX2NocmRldl9yZWdpb24oJmRldiwgMCwN CisJCQkJc2lzX2NoYXJfZGV2c19jb3VudCwgREVWSUNFX05BTUUpOw0KKwlpZiAocmV0KQ0KKwkJ cmV0dXJuIHJldDsNCisNCisJc2lzX2NoYXJfbWFqb3IgPSBNQUpPUihkZXYpOw0KKwljZGV2X2lu aXQoJnNpc19jaGFyX2NkZXYsICZzaXNfY2Rldl9mb3BzKTsNCisJc2lzX2NoYXJfY2Rldi5vd25l ciA9IFRISVNfTU9EVUxFOw0KKwlyZXQgPSBjZGV2X2FkZCgmc2lzX2NoYXJfY2RldiwgZGV2LCBz aXNfY2hhcl9kZXZzX2NvdW50KTsNCisJaWYgKHJldCkNCisJCWdvdG8gZXJyMTsNCisNCisJcHJf aW5mbygiJXMgZHJpdmVyKG1ham9yICVkKSBpbnN0YWxsZWQuXG4iLA0KKwkJCURFVklDRV9OQU1F LCBzaXNfY2hhcl9tYWpvcik7DQorCS8qcmVnaXN0ZXIgY2xhc3MqLw0KKwlzaXNfY2hhcl9jbGFz cyA9IGNsYXNzX2NyZWF0ZShUSElTX01PRFVMRSwgREVWSUNFX05BTUUpOw0KKwlpZiAoSVNfRVJS KHNpc19jaGFyX2NsYXNzKSkgew0KKwkJcmV0ID0gUFRSX0VSUihzaXNfY2hhcl9jbGFzcyk7DQor CQlnb3RvIGVycjI7DQorCX0NCisNCisJY2xhc3NfZGV2ID0gZGV2aWNlX2NyZWF0ZShzaXNfY2hh cl9jbGFzcywgTlVMTCwgZGV2LCBOVUxMLCBERVZJQ0VfTkFNRSk7DQorCWlmIChJU19FUlIoY2xh c3NfZGV2KSkgew0KKwkJcmV0ID0gUFRSX0VSUihjbGFzc19kZXYpOw0KKwkJZ290byBlcnIzOw0K Kwl9DQorDQorCXJldHVybiAwOw0KK2VycjM6DQorCWNsYXNzX2Rlc3Ryb3koc2lzX2NoYXJfY2xh c3MpOw0KKwlzaXNfY2hhcl9jbGFzcyA9IE5VTEw7DQorZXJyMjoNCisJY2Rldl9kZWwoJnNpc19j aGFyX2NkZXYpOw0KKwltZW1zZXQoJnNpc19jaGFyX2NkZXYsIDAsIHNpemVvZihzdHJ1Y3QgY2Rl dikpOw0KK2VycjE6DQorCXNpc19jaGFyX21ham9yID0gMDsNCisJdW5yZWdpc3Rlcl9jaHJkZXZf cmVnaW9uKGRldiwgc2lzX2NoYXJfZGV2c19jb3VudCk7DQorCXJldHVybiByZXQ7DQorfQ0KKw0K K3N0YXRpYyB2b2lkIHNpc19kZWluaXRfY2hhcmRldih2b2lkKQ0KK3sNCisJZGV2X3QgZGV2ID0g TUtERVYoc2lzX2NoYXJfbWFqb3IsIDApOw0KKw0KKwlpZiAoc2lzX2NoYXJfY2xhc3MpIHsNCisJ CXByX2luZm8oInNpc19kZWluaXRfY2hhcmRldlxuIik7DQorCQlkZXZpY2VfZGVzdHJveShzaXNf Y2hhcl9jbGFzcywgZGV2KTsNCisJCWNsYXNzX2Rlc3Ryb3koc2lzX2NoYXJfY2xhc3MpOw0KKwkJ c2lzX2NoYXJfY2xhc3MgPSBOVUxMOw0KKwkJY2Rldl9kZWwoJnNpc19jaGFyX2NkZXYpOw0KKwkJ bWVtc2V0KCZzaXNfY2hhcl9jZGV2LCAwLCBzaXplb2Yoc3RydWN0IGNkZXYpKTsNCisJCXNpc19j aGFyX21ham9yID0gMDsNCisJCXVucmVnaXN0ZXJfY2hyZGV2X3JlZ2lvbihkZXYsIHNpc19jaGFy X2RldnNfY291bnQpOw0KKwl9DQorfQ0KKyNlbmRpZg0KKw0KK3N0YXRpYyBpbnQgc2lzX3RzX3By b2JlKA0KKwlzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50LCBjb25zdCBzdHJ1Y3QgaTJjX2Rldmlj ZV9pZCAqaWQpDQorew0KKwlpbnQgcmV0ID0gMDsNCisJc3RydWN0IHNpc190c19kYXRhICp0cyA9 IE5VTEw7DQorCXN0cnVjdCBzaXNfaTJjX3JtaV9wbGF0Zm9ybV9kYXRhICpwZGF0YSA9IE5VTEw7 DQorDQorCXByX2luZm8oInNpc190c19wcm9iZVxuIik7DQorCVRQSW5mbyA9IGt6YWxsb2Moc2l6 ZW9mKHN0cnVjdCBzaXNUUF9kcml2ZXJfZGF0YSksIEdGUF9LRVJORUwpOw0KKwlpZiAoVFBJbmZv ID09IE5VTEwpIHsNCisJCXJldCA9IC1FTk9NRU07DQorCQlnb3RvIGVycl9hbGxvY19kYXRhX2Zh aWxlZDsNCisJfQ0KKwl0cyA9IGt6YWxsb2Moc2l6ZW9mKHN0cnVjdCBzaXNfdHNfZGF0YSksIEdG UF9LRVJORUwpOw0KKwlpZiAodHMgPT0gTlVMTCkgew0KKwkJcmV0ID0gLUVOT01FTTsNCisJCWdv dG8gZXJyX2FsbG9jX2RhdGFfZmFpbGVkOw0KKwl9DQorCXRzX2JhayA9IHRzOw0KKwltdXRleF9p bml0KCZ0cy0+bXV0ZXhfd3EpOw0KKwkvKjEuIEluaXQgV29yayBxdWV1ZSBhbmQgbmVjZXNzYXJ5 IGJ1ZmZlcnMqLw0KKwlJTklUX1dPUksoJnRzLT53b3JrLCBzaXNfdHNfd29ya19mdW5jKTsNCisJ dHMtPmNsaWVudCA9IGNsaWVudDsNCisJaTJjX3NldF9jbGllbnRkYXRhKGNsaWVudCwgdHMpOw0K KwlwZGF0YSA9IGNsaWVudC0+ZGV2LnBsYXRmb3JtX2RhdGE7DQorCWlmIChwZGF0YSkNCisJCXRz LT5wb3dlciA9IHBkYXRhLT5wb3dlcjsNCisJaWYgKHRzLT5wb3dlcikgew0KKwkJcmV0ID0gdHMt PnBvd2VyKDEpOw0KKwkJaWYgKHJldCA8IDApIHsNCisJCQlwcl9lcnIoInNpc190c19wcm9iZSBw b3dlciBvbiBmYWlsZWRcbiIpOw0KKwkJCWdvdG8gZXJyX3Bvd2VyX2ZhaWxlZDsNCisJCX0NCisJ fQ0KKwkvKjIuIEFsbG9jYXRlIGlucHV0IGRldmljZSovDQorCXRzLT5pbnB1dF9kZXYgPSBpbnB1 dF9hbGxvY2F0ZV9kZXZpY2UoKTsNCisJaWYgKHRzLT5pbnB1dF9kZXYgPT0gTlVMTCkgew0KKwkJ cmV0ID0gLUVOT01FTTsNCisJCXByX2Vycigic2lzX3RzX3Byb2JlOiBGYWlsZWQgdG8gYWxsb2Nh dGUgaW5wdXQgZGV2aWNlXG4iKTsNCisJCWdvdG8gZXJyX2lucHV0X2Rldl9hbGxvY19mYWlsZWQ7 DQorCX0NCisJLypUaGlzIGlucHV0IGRldmljZSBuYW1lIHNob3VsZCBiZSB0aGUgc2FtZSB0byBJ REMgZmlsZSBuYW1lLiovDQorCXRzLT5pbnB1dF9kZXYtPm5hbWUgPSAic2lzX3RvdWNoIjsNCisN CisJc2V0X2JpdChFVl9BQlMsIHRzLT5pbnB1dF9kZXYtPmV2Yml0KTsNCisJc2V0X2JpdChFVl9L RVksIHRzLT5pbnB1dF9kZXYtPmV2Yml0KTsNCisJc2V0X2JpdChBQlNfTVRfUE9TSVRJT05fWCwg dHMtPmlucHV0X2Rldi0+YWJzYml0KTsNCisJc2V0X2JpdChBQlNfTVRfUE9TSVRJT05fWSwgdHMt PmlucHV0X2Rldi0+YWJzYml0KTsNCisJc2V0X2JpdChBQlNfTVRfVFJBQ0tJTkdfSUQsIHRzLT5p bnB1dF9kZXYtPmFic2JpdCk7DQorCXNldF9iaXQoSU5QVVRfUFJPUF9ESVJFQ1QsIHRzLT5pbnB1 dF9kZXYtPnByb3BiaXQpOw0KKwlzZXRfYml0KEFCU19NVF9QUkVTU1VSRSwgdHMtPmlucHV0X2Rl di0+YWJzYml0KTsNCisJc2V0X2JpdChBQlNfTVRfVE9VQ0hfTUFKT1IsIHRzLT5pbnB1dF9kZXYt PmFic2JpdCk7DQorCXNldF9iaXQoQUJTX01UX1RPVUNIX01JTk9SLCB0cy0+aW5wdXRfZGV2LT5h YnNiaXQpOw0KKwlpbnB1dF9zZXRfYWJzX3BhcmFtcyh0cy0+aW5wdXRfZGV2LCBBQlNfTVRfUFJF U1NVUkUsDQorCQkJCQkJMCwgUFJFU1NVUkVfTUFYLCAwLCAwKTsNCisJaW5wdXRfc2V0X2Fic19w YXJhbXModHMtPmlucHV0X2RldiwgQUJTX01UX1RPVUNIX01BSk9SLA0KKwkJCQkJCTAsIEFSRUFf TEVOR1RIX0xPTkdFUiwgMCwgMCk7DQorCWlucHV0X3NldF9hYnNfcGFyYW1zKHRzLT5pbnB1dF9k ZXYsIEFCU19NVF9UT1VDSF9NSU5PUiwNCisJCQkJCQkwLCBBUkVBX0xFTkdUSF9TSE9SVCwgMCwg MCk7DQorCWlucHV0X3NldF9hYnNfcGFyYW1zKHRzLT5pbnB1dF9kZXYsIEFCU19NVF9QT1NJVElP Tl9YLA0KKwkJCQkJCTAsIFNJU19NQVhfWCwgMCwgMCk7DQorCWlucHV0X3NldF9hYnNfcGFyYW1z KHRzLT5pbnB1dF9kZXYsIEFCU19NVF9QT1NJVElPTl9ZLA0KKwkJCQkJCTAsIFNJU19NQVhfWSwg MCwgMCk7DQorCWlucHV0X3NldF9hYnNfcGFyYW1zKHRzLT5pbnB1dF9kZXYsIEFCU19NVF9UUkFD S0lOR19JRCwNCisJCQkJCQkwLCAxNSwgMCwgMCk7DQorCS8qIGFkZCBmb3IgdG91Y2gga2V5cyAq Lw0KKwlzZXRfYml0KEtFWV9DT01QT1NFLCB0cy0+aW5wdXRfZGV2LT5rZXliaXQpOw0KKwlzZXRf Yml0KEtFWV9CQUNLLCB0cy0+aW5wdXRfZGV2LT5rZXliaXQpOw0KKwlzZXRfYml0KEtFWV9NRU5V LCB0cy0+aW5wdXRfZGV2LT5rZXliaXQpOw0KKwlzZXRfYml0KEtFWV9IT01FLCB0cy0+aW5wdXRf ZGV2LT5rZXliaXQpOw0KKwkvKjMuIFJlZ2lzdGVyIGlucHV0IGRldmljZSB0byBjb3JlKi8NCisJ cmV0ID0gaW5wdXRfcmVnaXN0ZXJfZGV2aWNlKHRzLT5pbnB1dF9kZXYpOw0KKwlpZiAocmV0KSB7 DQorCQlwcl9lcnIoInNpc190c19wcm9iZTogVW5hYmxlIHRvIHJlZ2lzdGVyICVzIGlucHV0IGRl dmljZVxuIiwNCisJCQkJdHMtPmlucHV0X2Rldi0+bmFtZSk7DQorCQlnb3RvIGVycl9pbnB1dF9y ZWdpc3Rlcl9kZXZpY2VfZmFpbGVkOw0KKwl9DQorCS8qNC4gaXJxIG9yIHRpbWVyIHNldHVwKi8N CisJcmV0ID0gaW5pdGlhbF9pcnEoKTsNCisJaWYgKHJldCA+PSAwKSB7DQorCQljbGllbnQtPmly cSA9IGdwaW9fdG9faXJxKEdQSU9fSVJRKTsNCisJCXJldCA9IHJlcXVlc3RfaXJxKGNsaWVudC0+ aXJxLCBzaXNfdHNfaXJxX2hhbmRsZXIsDQorCQkJCQlJUlFGX1RSSUdHRVJfRkFMTElORywgY2xp ZW50LT5uYW1lLCB0cyk7DQorCQlpZiAocmV0ID09IDApDQorCQkJdHMtPnVzZV9pcnEgPSAxOw0K KwkJZWxzZQ0KKwkJCWRldl9lcnIoJmNsaWVudC0+ZGV2LCAicmVxdWVzdF9pcnEgZmFpbGVkXG4i KTsNCisJfQ0KKwl0cy0+ZGVzYyA9IGlycV90b19kZXNjKHRzX2Jhay0+Y2xpZW50LT5pcnEpOw0K KwlocnRpbWVyX2luaXQoJnRzLT50aW1lciwgQ0xPQ0tfTU9OT1RPTklDLCBIUlRJTUVSX01PREVf UkVMKTsNCisJdHMtPnRpbWVyLmZ1bmN0aW9uID0gc2lzX3RzX3RpbWVyX2Z1bmM7DQorCWlmICgh dHMtPnVzZV9pcnEpDQorCQlocnRpbWVyX3N0YXJ0KCZ0cy0+dGltZXIsIGt0aW1lX3NldCgxLCAw KSwgSFJUSU1FUl9NT0RFX1JFTCk7DQorI2lmZGVmIENPTkZJR19IQVNfRUFSTFlTVVNQRU5EDQor CXRzLT5lYXJseV9zdXNwZW5kLmxldmVsID0gRUFSTFlfU1VTUEVORF9MRVZFTF9CTEFOS19TQ1JF RU4gKyAxOw0KKwl0cy0+ZWFybHlfc3VzcGVuZC5zdXNwZW5kID0gc2lzX3RzX2Vhcmx5X3N1c3Bl bmQ7DQorCXRzLT5lYXJseV9zdXNwZW5kLnJlc3VtZSA9IHNpc190c19sYXRlX3Jlc3VtZTsNCisJ cmVnaXN0ZXJfZWFybHlfc3VzcGVuZCgmdHMtPmVhcmx5X3N1c3BlbmQpOw0KKyNlbmRpZg0KKwlw cl9pbmZvKCJzaXNfdHNfcHJvYmU6IFN0YXJ0IHRvdWNoc2NyZWVuICVzIGluICVzIG1vZGVcbiIs DQorCQkJdHMtPmlucHV0X2Rldi0+bmFtZSwNCisJCQl0cy0+dXNlX2lycSA/ICJpbnRlcnJ1cHQi IDogInBvbGxpbmciKTsNCisJaWYgKHRzLT51c2VfaXJxKSB7DQorI2lmZGVmIF9JTlRfTU9ERV8x DQorCQlwcl9pbmZvKCJzaXNfdHNfcHJvYmU6IGludGVycnVwdCBjYXNlIDEgbW9kZVxuIik7DQor I2Vsc2UNCisJCXByX2luZm8oInNpc190c19wcm9iZTogaW50ZXJydXB0IGNhc2UgMiBtb2RlXG4i KTsNCisjZW5kaWYNCisJfQ0KKyNpZmRlZiBfU1REX1JXX0lPDQorCXJldCA9IHNpc19zZXR1cF9j aGFyZGV2KHRzKTsNCisJaWYgKHJldCkNCisJCXByX2Vycigic2lzX3NldHVwX2NoYXJkZXYgZmFp bFxuIik7DQorI2VuZGlmDQorCXByX2luZm8oInNpcyBTSVNfU0xBVkVfQUREUjogJWRcbiIsIFNJ U19TTEFWRV9BRERSKTsNCisJcmV0dXJuIDA7DQorZXJyX2lucHV0X3JlZ2lzdGVyX2RldmljZV9m YWlsZWQ6DQorCWlucHV0X2ZyZWVfZGV2aWNlKHRzLT5pbnB1dF9kZXYpOw0KK2Vycl9pbnB1dF9k ZXZfYWxsb2NfZmFpbGVkOg0KK2Vycl9wb3dlcl9mYWlsZWQ6DQorCWtmcmVlKHRzKTsNCitlcnJf YWxsb2NfZGF0YV9mYWlsZWQ6DQorCXJldHVybiByZXQ7DQorfQ0KKw0KK3N0YXRpYyBpbnQgc2lz X3RzX3JlbW92ZShzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50KQ0KK3sNCisJc3RydWN0IHNpc190 c19kYXRhICp0cyA9IGkyY19nZXRfY2xpZW50ZGF0YShjbGllbnQpOw0KKyNpZmRlZiBDT05GSUdf SEFTX0VBUkxZU1VTUEVORA0KKwl1bnJlZ2lzdGVyX2Vhcmx5X3N1c3BlbmQoJnRzLT5lYXJseV9z dXNwZW5kKTsNCisjZW5kaWYNCisjaWZkZWYgX1NURF9SV19JTw0KKwlzaXNfZGVpbml0X2NoYXJk ZXYoKTsNCisjZW5kaWYNCisJaWYgKHRzLT51c2VfaXJxKQ0KKwkJZnJlZV9pcnEoY2xpZW50LT5p cnEsIHRzKTsNCisJZWxzZQ0KKwkJaHJ0aW1lcl9jYW5jZWwoJnRzLT50aW1lcik7DQorCWlucHV0 X3VucmVnaXN0ZXJfZGV2aWNlKHRzLT5pbnB1dF9kZXYpOw0KKwlrZnJlZSh0cyk7DQorCXJldHVy biAwOw0KK30NCisNCitzdGF0aWMgaW50IHNpc190c19zdXNwZW5kKHN0cnVjdCBpMmNfY2xpZW50 ICpjbGllbnQsIHBtX21lc3NhZ2VfdCBtZXNnKQ0KK3sNCisJaW50IHJldCA9IDA7DQorCXN0cnVj dCBzaXNfdHNfZGF0YSAqdHMgPSBpMmNfZ2V0X2NsaWVudGRhdGEoY2xpZW50KTsNCisNCisJVFBJ bmZvLT5wcmVfa2V5Yml0X3N0YXRlID0gMHgwOw0KKw0KKwlpZiAodHMtPnVzZV9pcnEpIHsNCisJ CWlmICghaXJxZF9pcnFfZGlzYWJsZWQoJnRzLT5kZXNjLT5pcnFfZGF0YSkpDQorCQkJZGlzYWJs ZV9pcnEoY2xpZW50LT5pcnEpOw0KKwl9IGVsc2UNCisJCWhydGltZXJfY2FuY2VsKCZ0cy0+dGlt ZXIpOw0KKwlmbHVzaF93b3JrcXVldWUoc2lzX3dxKTsJCS8qb25seSBmbHVzaCBzaXNfd3EqLw0K Kw0KKw0KKwlpZiAodHMtPnBvd2VyKSB7DQorCQlyZXQgPSB0cy0+cG93ZXIoMCk7DQorCQlpZiAo cmV0IDwgMCkNCisJCQlwcl9lcnIoInNpc190c19zdXNwZW5kIHBvd2VyIG9mZiBmYWlsZWRcbiIp Ow0KKwl9DQorDQorCXJldHVybiAwOw0KK30NCisNCitzdGF0aWMgaW50IHNpc190c19yZXN1bWUo c3RydWN0IGkyY19jbGllbnQgKmNsaWVudCkNCit7DQorCWludCByZXQgPSAwOw0KKwlzdHJ1Y3Qg c2lzX3RzX2RhdGEgKnRzID0gaTJjX2dldF9jbGllbnRkYXRhKGNsaWVudCk7DQorDQorCWlmICh0 cy0+cG93ZXIpIHsNCisJCXJldCA9IHRzLT5wb3dlcigxKTsNCisJCWlmIChyZXQgPCAwKQ0KKwkJ CXByX2Vycigic2lzX3RzX3Jlc3VtZSBwb3dlciBvbiBmYWlsZWRcbiIpOw0KKwl9DQorDQorCWlm ICh0cy0+dXNlX2lycSkgew0KKwkJaWYgKGlycWRfaXJxX2Rpc2FibGVkKCZ0cy0+ZGVzYy0+aXJx X2RhdGEpKQ0KKwkJCWVuYWJsZV9pcnEoY2xpZW50LT5pcnEpOw0KKwl9IGVsc2UNCisJCWhydGlt ZXJfc3RhcnQoJnRzLT50aW1lciwga3RpbWVfc2V0KDEsIDApLCBIUlRJTUVSX01PREVfUkVMKTsN CisJcmV0dXJuIDA7DQorfQ0KKw0KKyNpZmRlZiBDT05GSUdfSEFTX0VBUkxZU1VTUEVORA0KK3N0 YXRpYyB2b2lkIHNpc190c19lYXJseV9zdXNwZW5kKHN0cnVjdCBlYXJseV9zdXNwZW5kICpoKQ0K K3sNCisJc3RydWN0IHNpc190c19kYXRhICp0czsNCisNCisJVFBJbmZvLT5wcmVfa2V5Yml0X3N0 YXRlID0gMHgwOw0KKwl0cyA9IGNvbnRhaW5lcl9vZihoLCBzdHJ1Y3Qgc2lzX3RzX2RhdGEsIGVh cmx5X3N1c3BlbmQpOw0KKwlzaXNfdHNfc3VzcGVuZCh0cy0+Y2xpZW50LCBQTVNHX1NVU1BFTkQp Ow0KK30NCisNCitzdGF0aWMgdm9pZCBzaXNfdHNfbGF0ZV9yZXN1bWUoc3RydWN0IGVhcmx5X3N1 c3BlbmQgKmgpDQorew0KKwlzdHJ1Y3Qgc2lzX3RzX2RhdGEgKnRzOw0KKw0KKwl0cyA9IGNvbnRh aW5lcl9vZihoLCBzdHJ1Y3Qgc2lzX3RzX2RhdGEsIGVhcmx5X3N1c3BlbmQpOw0KKwlzaXNfdHNf cmVzdW1lKHRzLT5jbGllbnQpOw0KK30NCisjZW5kaWYNCisNCisjaWZkZWYgQ09ORklHX1g4Ng0K Ky8qIFJldHVybiAwIGlmIGRldGVjdGlvbiBpcyBzdWNjZXNzZnVsLCAtRU5PREVWIG90aGVyd2lz ZSAqLw0KK3N0YXRpYyBpbnQgc2lzX3RzX2RldGVjdChzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50 LA0KKwkJICAgICAgIHN0cnVjdCBpMmNfYm9hcmRfaW5mbyAqaW5mbykNCit7DQorCWNvbnN0IGNo YXIgKnR5cGVfbmFtZTsNCisNCisJcHJfaW5mbygic2lzX3RzX2RldGVjdFxuIik7DQorCXR5cGVf bmFtZSA9ICJzaXNfaTJjX3RzIjsNCisJc3RybGNweShpbmZvLT50eXBlLCB0eXBlX25hbWUsIEky Q19OQU1FX1NJWkUpOw0KKwlyZXR1cm4gMDsNCit9DQorI2VuZGlmDQorDQorc3RhdGljIGNvbnN0 IHN0cnVjdCBpMmNfZGV2aWNlX2lkIHNpc190c19pZFtdID0gew0KKwl7IFNJU19JMkNfTkFNRSwg MCB9LA0KKwl7IH0NCit9Ow0KKw0KK01PRFVMRV9ERVZJQ0VfVEFCTEUoaTJjLCBzaXNfdHNfaWQp Ow0KKw0KK3N0YXRpYyBzdHJ1Y3QgaTJjX2RyaXZlciBzaXNfdHNfZHJpdmVyID0gew0KKwkucHJv YmUJCT0gc2lzX3RzX3Byb2JlLA0KKwkucmVtb3ZlCQk9IHNpc190c19yZW1vdmUsDQorI2lmbmRl ZiBDT05GSUdfSEFTX0VBUkxZU1VTUEVORA0KKwkuc3VzcGVuZAk9IHNpc190c19zdXNwZW5kLA0K KwkucmVzdW1lCQk9IHNpc190c19yZXN1bWUsDQorI2VuZGlmDQorI2lmZGVmIENPTkZJR19YODYN CisJLmNsYXNzCQk9IEkyQ19DTEFTU19IV01PTiwNCisJLmRldGVjdAkJPSBzaXNfdHNfZGV0ZWN0 LA0KKwkuYWRkcmVzc19saXN0CT0gbm9ybWFsX2kyYywNCisjZW5kaWYNCisJLmlkX3RhYmxlCT0g c2lzX3RzX2lkLA0KKwkuZHJpdmVyID0gew0KKwkJLm5hbWUJPSBTSVNfSTJDX05BTUUsDQorCX0s DQorfTsNCisNCitzdGF0aWMgaW50IF9faW5pdCBzaXNfdHNfaW5pdCh2b2lkKQ0KK3sNCisJcHJf aW5mbygic2lzX3RzX2luaXRcbiIpOw0KKwlzaXNfd3EgPSBjcmVhdGVfc2luZ2xldGhyZWFkX3dv cmtxdWV1ZSgic2lzX3dxIik7DQorDQorCWlmICghc2lzX3dxKQ0KKwkJcmV0dXJuIC1FTk9NRU07 DQorCXJldHVybiBpMmNfYWRkX2RyaXZlcigmc2lzX3RzX2RyaXZlcik7DQorfQ0KKw0KK3N0YXRp YyB2b2lkIF9fZXhpdCBzaXNfdHNfZXhpdCh2b2lkKQ0KK3sNCisJcHJfaW5mbygic2lzX3RzX2V4 aXRcbiIpOw0KKwlpMmNfZGVsX2RyaXZlcigmc2lzX3RzX2RyaXZlcik7DQorCWlmIChzaXNfd3Ep DQorCQlkZXN0cm95X3dvcmtxdWV1ZShzaXNfd3EpOw0KK30NCisNCittb2R1bGVfaW5pdChzaXNf dHNfaW5pdCk7DQorbW9kdWxlX2V4aXQoc2lzX3RzX2V4aXQpOw0KK01PRFVMRV9ERVNDUklQVElP TigiU2lTIDkyMDAgRmFtaWx5IFRvdWNoc2NyZWVuIERyaXZlciIpOw0KK01PRFVMRV9MSUNFTlNF KCJHUEwiKTsNCmRpZmYgLS1naXQgYS9saW51eC0zLjE4LjUvZHJpdmVycy9pbnB1dC90b3VjaHNj cmVlbi9zaXNfaTJjLmggYi9saW51eC0zLjE4LjUvZHJpdmVycy9pbnB1dC90b3VjaHNjcmVlbi9z aXNfaTJjLmgNCm5ldyBmaWxlIG1vZGUgMTAwNjQ0DQppbmRleCAwMDAwMDAwLi43NjM5YTUyDQot LS0gL2Rldi9udWxsDQorKysgYi9saW51eC0zLjE4LjUvZHJpdmVycy9pbnB1dC90b3VjaHNjcmVl bi9zaXNfaTJjLmgNCkBAIC0wLDAgKzEsMTczIEBADQorLyoNCisgKiBpbmNsdWRlL2xpbnV4L3Np c19pMmMuaCAtIHBsYXRmb3JtIGRhdGEgc3RydWN0dXJlIGZvciBTaVMgOTIwMCBmYW1pbHkNCisg Kg0KKyAqIENvcHlyaWdodCAoQykgMjAxMSBTaVMsIEluYy4NCisgKg0KKyAqIFRoaXMgc29mdHdh cmUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMN CisgKiBMaWNlbnNlIHZlcnNpb24gMiwgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJl IEZvdW5kYXRpb24sIGFuZA0KKyAqIG1heSBiZSBjb3BpZWQsIGRpc3RyaWJ1dGVkLCBhbmQgbW9k aWZpZWQgdW5kZXIgdGhvc2UgdGVybXMuDQorICoNCisgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJp YnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwNCisgKiBidXQgV0lUSE9V VCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZg0KKyAq IE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNl ZSB0aGUNCisgKiBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLg0K KyAqDQorICogRGF0ZTogMjAxNS8wMS8xNQ0KKyAqIFZlcnNpb246CUFuZHJvaWRfdjIuMDUuMDAt QTYzOS0xMTEzDQorICovDQorI2luY2x1ZGUgPGxpbnV4L3ZlcnNpb24uaD4NCisNCisjaWZuZGVm IF9MSU5VWF9TSVNfSTJDX0gNCisjZGVmaW5lIF9MSU5VWF9TSVNfSTJDX0gNCisNCisNCisjZGVm aW5lIFNJU19JMkNfTkFNRSAic2lzX2kyY190cyINCisjZGVmaW5lIFNJU19TTEFWRV9BRERSCQkJ CQkweDVjDQorLyoxMG1zKi8NCisjZGVmaW5lIFRJTUVSX05TCQkJCQkJMTAwMDAwMDANCisjZGVm aW5lIE1BWF9GSU5HRVJTCQkJCQkJMTANCisNCisvKiBGb3Igc3RhbmRhcmQgUi9XIElPICggU2lT IGZpcm13YXJlIGFwcGxpY2F0aW9uICkqLw0KKyNkZWZpbmUgX1NURF9SV19JTwkJCQkJCS8qT04v T0ZGKi8NCisNCisvKiBDaGVjayBkYXRhIENSQyAqLw0KKy8qI2RlZmluZSBfQ0hFQ0tfQ1JDKi8J CQkJCQkvKk9OL09GRiovDQorDQorLyogSW50ZXJydXB0IHNldHRpbmcgYW5kIG1vZGVzICovDQor I2RlZmluZSBfSTJDX0lOVF9FTkFCTEUJCQkJCS8qT04vT0ZGKi8NCisjZGVmaW5lIEdQSU9fSVJR CQkJCQkJMTMzDQorDQorLyoJRW5hYmxlIGlmIHVzZSBpbnRlcnJ1cHQgY2FzZSAxIG1vZGUuCSov DQorLyoJRGlzYWJsZSBpZiB1c2UgaW50ZXJydXB0IGNhc2UgMiBtb2RlLgkqLw0KKy8qI2RlZmlu ZSBfSU5UX01PREVfMSovCQkJCQkvKk9OL09GRiovDQorDQorLyogUmVzb2x1dGlvbiBtb2RlICov DQorLypDb25zdGFudCB2YWx1ZSovDQorI2RlZmluZSBTSVNfTUFYX1gJCQkJCQk0MDk1DQorI2Rl ZmluZSBTSVNfTUFYX1kJCQkJCQk0MDk1DQorDQorI2RlZmluZSBPTkVfQllURQkJCQkJCTENCisj ZGVmaW5lIEZJVkVfQllURQkJCQkJCTUNCisjZGVmaW5lIEVJR0hUX0JZVEUJCQkJCQk4DQorI2Rl ZmluZSBTSVhURUVOX0JZVEUJCQkJCTE2DQorI2RlZmluZSBQQUNLRVRfQlVGRkVSX1NJWkUJCQkJ MTI4DQorDQorI2RlZmluZSBTSVNfQ01EX05PUk1BTAkJCQkJMHgwDQorI2RlZmluZSBTSVNfQ01E X1NPRlRSRVNFVAkJCQkweDgyDQorI2RlZmluZSBTSVNfQ01EX1JFQ0FMSUJSQVRFCQkJCTB4ODcN CisjZGVmaW5lIFNJU19DTURfUE9XRVJNT0RFCQkJCTB4OTANCisjZGVmaW5lIE1TS19UT1VDSE5V TQkJCQkJMHgwZg0KKyNkZWZpbmUgTVNLX0hBU19DUkMJCQkJCQkweDEwDQorI2RlZmluZSBNU0tf REFUQUZNVAkJCQkJCTB4ZTANCisjZGVmaW5lIE1TS19QU1RBVEUJCQkJCQkweDBmDQorI2RlZmlu ZSBNU0tfUElECQkJCQkJCTB4ZjANCisjZGVmaW5lIFJFU19GTVQJCQkJCQkJMHgwMA0KKyNkZWZp bmUgRklYX0ZNVAkJCQkJCQkweDQwDQorDQorLyogZm9yIG5ldyBpMmMgZm9ybWF0ICovDQorI2Rl ZmluZSBUT1VDSERPV04JCQkJCQkweDMNCisjZGVmaW5lIFRPVUNIVVAJCQkJCQkJMHgwDQorI2Rl ZmluZSBNQVhfQllURQkJCQkJCTY0DQorI2RlZmluZQlQUkVTU1VSRV9NQVgJCQkJCTI1NQ0KKw0K Ky8qUmVzb2x1dGlvbiBkaWFnb25hbCAqLw0KKyNkZWZpbmUgQVJFQV9MRU5HVEhfTE9OR0VSCQkJ CTU3OTINCisvKigoU0lTX01BWF9YXjIpICsgKFNJU19NQVhfWV4yKSleMC41Ki8NCisjZGVmaW5l IEFSRUFfTEVOR1RIX1NIT1JUCQkJCTU3OTINCisjZGVmaW5lIEFSRUFfVU5JVAkJCQkJCSg1Nzky LzMyKQ0KKw0KKw0KKyNkZWZpbmUgRk9STUFUX01PREUJCQkJCQkxDQorDQorI2RlZmluZSBNU0tf Tk9CVE4JCQkJCQkwDQorI2RlZmluZSBNU0tfQ09NUAkJCQkJCTENCisjZGVmaW5lIE1TS19CQUNL CQkJCQkJMg0KKyNkZWZpbmUgTVNLX01FTlUJCQkJCQk0DQorI2RlZmluZSBNU0tfSE9NRQkJCQkJ CTgNCisNCisjZGVmaW5lIFBfQllURUNPVU5UCQkJCQkJMA0KKyNkZWZpbmUgQUxMX0lOX09ORV9Q QUNLQUdFCQkJCTB4MTANCisjZGVmaW5lIElTX1RPVUNIKHgpCQkJCQkJKHggJiAweDEpDQorI2Rl ZmluZSBJU19ISURJMkMoeCkJCQkJCSgoeCAmIDB4RikgPT0gMHgwNikNCisjZGVmaW5lIElTX0FS RUEoeCkJCQkJCQkoKHggPj4gNCkgJiAweDEpDQorI2RlZmluZSBJU19QUkVTU1VSRSh4KQkJCQkg ICAgKCh4ID4+IDUpICYgMHgxKQ0KKyNkZWZpbmUgSVNfU0NBTlRJTUUoeCkJCQkgICAgICAgICgo eCA+PiA2KSAmIDB4MSkNCisvKiNkZWZpbmUgX0RFQlVHX1BBQ0tBR0UqLwkJCQkvKk9OL09GRiov DQorLyojZGVmaW5lIF9ERUJVR19SRVBPUlQqLwkJCQkvKk9OL09GRiovDQorI2RlZmluZSBOT1JN QUxfTEVOX1BFUl9QT0lOVAkJCTYNCisjZGVmaW5lIEFSRUFfTEVOX1BFUl9QT0lOVAkJCQkyDQor I2RlZmluZSBQUkVTU1VSRV9MRU5fUEVSX1BPSU5UCQkJMQ0KKw0KKyNkZWZpbmUgVE9VQ0hfRk9S TUFUCQkJCQkweDENCisjZGVmaW5lIEJVVFRPTl9GT1JNQVQJCQkJCTB4NA0KKyNkZWZpbmUgSElE STJDX0ZPUk1BVAkJCQkJMHg2DQorI2RlZmluZSBQX1JFUE9SVF9JRAkJCQkJCTINCisjZGVmaW5l IEJVVFRPTl9TVEFURQkJCQkJMw0KKyNkZWZpbmUgQlVUVE9OX0tFWV9DT1VOVAkJCQkxNg0KKyNk ZWZpbmUgQllURV9CWVRFQ09VTlQJCQkJCTINCisjZGVmaW5lIEJZVEVfQ09VTlQJCQkJCQkxDQor I2RlZmluZSBCWVRFX1JlcG9ydElECQkJCQkxDQorI2RlZmluZSBCWVRFX0NSQ19ISURJMkMJCQkJ CTANCisjZGVmaW5lIEJZVEVfQ1JDX0kyQwkJCQkJMg0KKyNkZWZpbmUgQllURV9TQ0FOVElNRQkJ CQkJMg0KKyNkZWZpbmUgTk9fVE9VQ0hfQllURUNPVU5UCQkJCTB4Mw0KKw0KKy8qIFRPRE8gKi8N CisjZGVmaW5lIFRPVUNIX1BPV0VSX1BJTgkJCQkJMA0KKyNkZWZpbmUgVE9VQ0hfUkVTRVRfUElO CQkJCQkxDQorDQorLyogQ01EIERlZmluZSAqLw0KKyNkZWZpbmUgQlVGX0FDS19QTEFDRV9MCQkJ CQk0DQorI2RlZmluZSBCVUZfQUNLX1BMQUNFX0gJCQkJCTUNCisjZGVmaW5lIEJVRl9BQ0tfTAkJ CQkJCTB4RUYNCisjZGVmaW5lIEJVRl9BQ0tfSAkJCQkJCTB4QkUNCisjZGVmaW5lIEJVRl9OQUNL X0wJCQkJCQkweEFEDQorI2RlZmluZSBCVUZfTkFDS19ICQkJCQkJMHhERQ0KKyNkZWZpbmUgQlVG X0NSQ19QTEFDRQkJCQkJNw0KKw0KKy8qIFNpUyBpMmMgZXJyb3IgY29kZSAqLw0KKyNkZWZpbmUg U0lTX0VSUgkJCQkJCS0xDQorI2RlZmluZSBTSVNfRVJSX0FDQ0VTU19VU0VSX01FTQkJLTExIC8q IEFjY2VzcyB1c2VyIG1lbW9yeSBmYWlsICovDQorI2RlZmluZSBTSVNfRVJSX0FMTE9DQVRFX0tF Uk5FTF9NRU0JLTEyIC8qIEFsbG9jYXRlIG1lbW9yeSBmYWlsICovDQorI2RlZmluZSBTSVNfRVJS X0NMSUVOVAkJCQktMTMgLyogQ2xpZW50IG5vdCBjcmVhdGVkICovDQorI2RlZmluZSBTSVNfRVJS X0NPUFlfRlJPTV9VU0VSCQktMTQgLyogQ29weSBkYXRhIGZyb20gdXNlciBmYWlsICovDQorI2Rl ZmluZSBTSVNfRVJSX0NPUFlfRlJPTV9LRVJORUwJLTE5IC8qIENvcHkgZGF0YSBmcm9tIGtlcm5l bCBmYWlsICovDQorI2RlZmluZSBTSVNfRVJSX1RSQU5TTUlUX0kyQwkJLTIxIC8qIFRyYW5zbWl0 IGVycm9yIGluIEkyQyAqLw0KKw0KK3N0cnVjdCBzaXNfaTJjX3JtaV9wbGF0Zm9ybV9kYXRhIHsN CisJaW50ICgqcG93ZXIpKGludCBvbik7CS8qIE9ubHkgdmFsaWQgaW4gZmlyc3QgYXJyYXkgZW50 cnkgKi8NCit9Ow0KKw0KK3N0cnVjdCBQb2ludCB7DQorCWludCBpZDsNCisJdW5zaWduZWQgc2hv cnQgeCwgeTsJCS8qdWludDE2X3QgPyovDQorCXVpbnQxNl90IFByZXNzdXJlOw0KKwl1aW50MTZf dCBXaWR0aDsNCisJdWludDE2X3QgSGVpZ2h0Ow0KK307DQorDQorc3RydWN0IHNpc1RQX2RyaXZl cl9kYXRhIHsNCisJaW50IGlkOw0KKwlpbnQgZmluZ2VyczsNCisJdWludDhfdCBwcmVfa2V5Yml0 X3N0YXRlOw0KKwlzdHJ1Y3QgUG9pbnQgcHRbTUFYX0ZJTkdFUlNdOw0KK307DQorDQorc3RydWN0 IHNpc190c19kYXRhIHsNCisJaW50ICgqcG93ZXIpKGludCBvbik7DQorCWludCB1c2VfaXJxOw0K KwlzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50Ow0KKwlzdHJ1Y3QgaW5wdXRfZGV2ICppbnB1dF9k ZXY7DQorCXN0cnVjdCBocnRpbWVyIHRpbWVyOw0KKwlzdHJ1Y3QgaXJxX2Rlc2MgKmRlc2M7DQor CXN0cnVjdCB3b3JrX3N0cnVjdCB3b3JrOw0KKwlzdHJ1Y3QgbXV0ZXggbXV0ZXhfd3E7DQorI2lm ZGVmIENPTkZJR19IQVNfRUFSTFlTVVNQRU5EDQorCXN0cnVjdCBlYXJseV9zdXNwZW5kIGVhcmx5 X3N1c3BlbmQ7DQorI2VuZGlmDQorfTsNCisNCitzdGF0aWMgaW50IHNpc190c19zdXNwZW5kKHN0 cnVjdCBpMmNfY2xpZW50ICpjbGllbnQsIHBtX21lc3NhZ2VfdCBtZXNnKTsNCitzdGF0aWMgaW50 IHNpc190c19yZXN1bWUoc3RydWN0IGkyY19jbGllbnQgKmNsaWVudCk7DQorDQorI2VuZGlmIC8q IF9MSU5VWF9TSVNfSTJDX0ggKi8NCg==