From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4366A1B3B32; Thu, 29 Aug 2024 16:27:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724948832; cv=none; b=X1AOIxd4SUUepJCXXC21gvRCtitEJ3s94xWP96Yt9OGbXvraZ7gCoZLoco2Pi8NL6uL+HdWXebYQCpuW3RE67LVMRt1s6dD/YpxIXY2g0Z9lX+b8CHpjmgbx2jI/FPf1vrLranvDFyrxX2cZi4XXlMcYH3F0F6tEcMRhQa/d2U8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724948832; c=relaxed/simple; bh=rUK7cYrfp3ANOIDU3rLaYOEYkyvnUKtRN7aNsL8GQDU=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=Ys7E0kmPQI/y7CRyNF4qNS7bJx0s2bYP0acBo513NG57ata5eTT3I7eT/vpji96EtT+c7ZBCSoW0k4Zli2ukjc8uWO2+L5s2WmBha4NjbRAGdD84W4yYD1Lje3m/CTV0+nD7Uy3FrdUHBf5Aoun378uEq27/spZu7KnCIzzi95o= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=J3aSAJAm; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="J3aSAJAm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DD8BFC4CEC2; Thu, 29 Aug 2024 16:27:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724948832; bh=rUK7cYrfp3ANOIDU3rLaYOEYkyvnUKtRN7aNsL8GQDU=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=J3aSAJAmkUXpSwt1M+icllnaM5UhiPpzeCpja5FEKOILNoHE1faNT1islB9c6BLzx Zr7sVdo+BZ4PvsEmCsflfnl/qt3C5gEGlRvHzB7aZnS43ZI7rtlS009Xm50T1zpjS7 MsYc70pcCEDEQCWonNnsm73gyxnunmxfdf4vsX7Pf8t2XT5S/mYPo3/g9S/qBPhODn GTFv2MbII2PA9H8Gk3xTFxcEzSf+1rE3nhDSUhQEvpON0zhy0S85i1P4OjXiNKaw0m 6tB2Psy+e0FKIiWS5xvXYoKDy478U2Ao5kbQ82ypDGhDa6jj5mflzN35tq91Lsx2jO L2iAgG//6rHqw== Date: Thu, 29 Aug 2024 17:27:05 +0100 From: Lee Jones To: Heiko Stuebner Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, jdelvare@suse.com, linux@roeck-us.net, dmitry.torokhov@gmail.com, pavel@ucw.cz, ukleinek@debian.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-input@vger.kernel.org, linux-leds@vger.kernel.org Subject: Re: [PATCH v6 3/7] leds: add driver for LEDs from qnap-mcu devices Message-ID: <20240829162705.GR6858@google.com> References: <20240825203235.1122198-1-heiko@sntech.de> <20240825203235.1122198-4-heiko@sntech.de> Precedence: bulk X-Mailing-List: linux-hwmon@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20240825203235.1122198-4-heiko@sntech.de> On Sun, 25 Aug 2024, Heiko Stuebner wrote: > This adds a driver that connects to the qnap-mcu mfd driver and provides > access to the LEDs on it. > > Signed-off-by: Heiko Stuebner > --- > MAINTAINERS | 1 + > drivers/leds/Kconfig | 11 ++ > drivers/leds/Makefile | 1 + > drivers/leds/leds-qnap-mcu.c | 226 +++++++++++++++++++++++++++++++++++ > 4 files changed, 239 insertions(+) > create mode 100644 drivers/leds/leds-qnap-mcu.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 0fbd2d953da4..4dff0e237f22 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -18657,6 +18657,7 @@ F: drivers/media/tuners/qm1d1c0042* > QNAP MCU DRIVER > M: Heiko Stuebner > S: Maintained > +F: drivers/leds/leds-qnap-mcu.c > F: drivers/mfd/qnap-mcu.c > F: include/linux/qnap-mcu.h > > diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig > index 8d9d8da376e4..9a337478dd80 100644 > --- a/drivers/leds/Kconfig > +++ b/drivers/leds/Kconfig > @@ -580,6 +580,17 @@ config LEDS_PCA995X > LED driver chips accessed via the I2C bus. Supported > devices include PCA9955BTW, PCA9952TW and PCA9955TW. > > +config LEDS_QNAP_MCU > + tristate "LED Support for QNAP MCU controllers" > + depends on LEDS_CLASS > + depends on MFD_QNAP_MCU > + help > + This option enables support for LEDs available on embedded > + controllers used in QNAP NAS devices. > + > + This driver can also be built as a module. If so, the module > + will be called qnap-mcu-leds. > + > config LEDS_WM831X_STATUS > tristate "LED support for status LEDs on WM831x PMICs" > depends on LEDS_CLASS > diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile > index 18afbb5a23ee..c6f74865d729 100644 > --- a/drivers/leds/Makefile > +++ b/drivers/leds/Makefile > @@ -79,6 +79,7 @@ obj-$(CONFIG_LEDS_PCA995X) += leds-pca995x.o > obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o > obj-$(CONFIG_LEDS_POWERNV) += leds-powernv.o > obj-$(CONFIG_LEDS_PWM) += leds-pwm.o > +obj-$(CONFIG_LEDS_QNAP_MCU) += leds-qnap-mcu.o > obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o > obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o > obj-$(CONFIG_LEDS_SUN50I_A100) += leds-sun50i-a100.o > diff --git a/drivers/leds/leds-qnap-mcu.c b/drivers/leds/leds-qnap-mcu.c > new file mode 100644 > index 000000000000..0723ec52e4c5 > --- /dev/null > +++ b/drivers/leds/leds-qnap-mcu.c > @@ -0,0 +1,226 @@ > +// SPDX-License-Identifier: GPL-2.0-only > + Superfluous line. > +/* > + * Driver for LEDs found on QNAP MCU devices > + * > + * Copyright (C) 2024 Heiko Stuebner > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +enum qnap_mcu_err_led_mode { > + QNAP_MCU_ERR_LED_ON = 0, > + QNAP_MCU_ERR_LED_OFF = 1, > + QNAP_MCU_ERR_LED_BLINK_FAST = 2, > + QNAP_MCU_ERR_LED_BLINK_SLOW = 3, > +}; > + > +struct qnap_mcu_err_led { > + struct qnap_mcu *mcu; > + struct led_classdev cdev; > + char name[LED_MAX_NAME_SIZE]; > + u8 num; > + u8 mode; > +}; > + > +static inline struct qnap_mcu_err_led * > + cdev_to_qnap_mcu_err_led(struct led_classdev *led_cdev) > +{ > + return container_of(led_cdev, struct qnap_mcu_err_led, cdev); > +} > + > +static int qnap_mcu_err_led_set(struct led_classdev *led_cdev, > + enum led_brightness value) 'value' is a terrible variable name. Please describe the data. 'brightness' seems appropriate. > +{ > + struct qnap_mcu_err_led *err_led = cdev_to_qnap_mcu_err_led(led_cdev); > + u8 cmd[] = { 0x40, 0x52, 0x30 + err_led->num, 0x30 }; Really not fan of these magic values being used raw like this. > + /* Don't disturb a possible set blink-mode if LED is already on */ Why not save cycles and return if blink mode is already enabled? > + if (value == 0) > + err_led->mode = QNAP_MCU_ERR_LED_OFF; > + else if (err_led->mode == QNAP_MCU_ERR_LED_OFF) > + err_led->mode = QNAP_MCU_ERR_LED_ON; Then you can do: err_led->mode = value ? QNAP_MCU_ERR_LED_ON : QNAP_MCU_ERR_LED_OFF; > + cmd[3] = 0x30 + err_led->mode; > + > + return qnap_mcu_exec_with_ack(err_led->mcu, cmd, sizeof(cmd)); > +} > + > +static int qnap_mcu_err_led_blink_set(struct led_classdev *led_cdev, > + unsigned long *delay_on, > + unsigned long *delay_off) > +{ > + struct qnap_mcu_err_led *err_led = cdev_to_qnap_mcu_err_led(led_cdev); > + u8 cmd[] = { 0x40, 0x52, 0x30 + err_led->num, 0x30 }; > + > + /* LED is off, nothing to do */ > + if (err_led->mode == QNAP_MCU_ERR_LED_OFF) > + return 0; > + > + if (*delay_on < 500) { Setting delay_on based on the current value of delay_on sounds sketchy. > + *delay_on = 100; > + *delay_off = 100; > + err_led->mode = QNAP_MCU_ERR_LED_BLINK_FAST; > + } else { > + *delay_on = 500; > + *delay_off = 500; > + err_led->mode = QNAP_MCU_ERR_LED_BLINK_SLOW; > + } How do you change from a fast to a slow blinking LED and back again? > + cmd[3] = 0x30 + err_led->mode; > + > + return qnap_mcu_exec_with_ack(err_led->mcu, cmd, sizeof(cmd)); > +} > + > +static int qnap_mcu_register_err_led(struct device *dev, struct qnap_mcu *mcu, int num) What's num? I should be able to answer that by the nomenclature. > +{ > + struct qnap_mcu_err_led *err_led; > + int ret; > + > + err_led = devm_kzalloc(dev, sizeof(*err_led), GFP_KERNEL); > + if (!err_led) > + return -ENOMEM; > + > + err_led->mcu = mcu; > + err_led->num = num; > + err_led->mode = QNAP_MCU_ERR_LED_OFF; > + > + snprintf(err_led->name, LED_MAX_NAME_SIZE, "hdd%d:red:status", num + 1); scnprintf()? > + err_led->cdev.name = err_led->name; > + > + err_led->cdev.brightness_set_blocking = qnap_mcu_err_led_set; > + err_led->cdev.blink_set = qnap_mcu_err_led_blink_set; > + err_led->cdev.brightness = 0; > + err_led->cdev.max_brightness = 1; > + > + ret = devm_led_classdev_register(dev, &err_led->cdev); > + if (ret) > + return dev_err_probe(dev, ret, "failed to register hdd led %d", num); "HDD LED" > + return qnap_mcu_err_led_set(&err_led->cdev, 0); > +} > + > +enum qnap_mcu_usb_led_mode { > + QNAP_MCU_USB_LED_ON = 1, > + QNAP_MCU_USB_LED_OFF = 3, > + QNAP_MCU_USB_LED_BLINK = 2, > +}; > + > +struct qnap_mcu_usb_led { > + struct qnap_mcu *mcu; > + struct led_classdev cdev; > + u8 mode; > +}; > + > +static inline struct qnap_mcu_usb_led * > + cdev_to_qnap_mcu_usb_led(struct led_classdev *led_cdev) > +{ > + return container_of(led_cdev, struct qnap_mcu_usb_led, cdev); > +} > + > +static int qnap_mcu_usb_led_set(struct led_classdev *led_cdev, > + enum led_brightness value) > +{ > + struct qnap_mcu_usb_led *usb_led = cdev_to_qnap_mcu_usb_led(led_cdev); > + u8 cmd[] = { 0x40, 0x43, 0 }; > + > + /* > + * If the led is off, turn it on. Otherwise don't disturb "LED" > + * a possible set blink-mode. > + */ > + if (value == 0) > + usb_led->mode = QNAP_MCU_USB_LED_OFF; > + else if (usb_led->mode == QNAP_MCU_USB_LED_OFF) > + usb_led->mode = QNAP_MCU_USB_LED_ON; Same suggestions as above. > + /* byte 3 is shared between the usb led target and setting the mode */ "Byte" for two reasons. Firstly because it's the correct capitalisation of Byte and secondly because it's the start of a sentence. "USB" and "LED" throughout please. > + cmd[2] = 0x44 | usb_led->mode; > + > + return qnap_mcu_exec_with_ack(usb_led->mcu, cmd, sizeof(cmd)); > +} > + > +static int qnap_mcu_usb_led_blink_set(struct led_classdev *led_cdev, > + unsigned long *delay_on, > + unsigned long *delay_off) > +{ > + struct qnap_mcu_usb_led *usb_led = cdev_to_qnap_mcu_usb_led(led_cdev); > + u8 cmd[] = { 0x40, 0x43, 0 }; > + > + /* LED is off, nothing to do */ > + if (usb_led->mode == QNAP_MCU_USB_LED_OFF) > + return 0; > + > + *delay_on = 250; > + *delay_off = 250; > + usb_led->mode = QNAP_MCU_USB_LED_BLINK; > + > + /* byte 3 is shared between the usb led target and setting the mode */ > + cmd[2] = 0x44 | usb_led->mode; > + > + return qnap_mcu_exec_with_ack(usb_led->mcu, cmd, sizeof(cmd)); > +} > + > +static int qnap_mcu_register_usb_led(struct device *dev, struct qnap_mcu *mcu) > +{ > + struct qnap_mcu_usb_led *usb_led; > + int ret; > + > + usb_led = devm_kzalloc(dev, sizeof(*usb_led), GFP_KERNEL); > + if (!usb_led) > + return -ENOMEM; > + > + usb_led->mcu = mcu; > + usb_led->mode = QNAP_MCU_USB_LED_OFF; > + usb_led->cdev.name = "usb:blue:disk"; > + usb_led->cdev.brightness_set_blocking = qnap_mcu_usb_led_set; > + usb_led->cdev.blink_set = qnap_mcu_usb_led_blink_set; > + usb_led->cdev.brightness = 0; > + usb_led->cdev.max_brightness = 1; > + > + ret = devm_led_classdev_register(dev, &usb_led->cdev); > + if (ret) > + return dev_err_probe(dev, ret, "failed to register usb led"); > + > + return qnap_mcu_usb_led_set(&usb_led->cdev, 0); > +} > + > +static int qnap_mcu_leds_probe(struct platform_device *pdev) > +{ > + struct qnap_mcu *mcu = dev_get_drvdata(pdev->dev.parent); > + const struct qnap_mcu_variant *variant = qnap_mcu_get_variant_data(mcu); Grab this from platform_data. > + int ret, i; > + > + for (i = 0; i < variant->num_drives; i++) { You can use: for (int i = 0; .. > + ret = qnap_mcu_register_err_led(&pdev->dev, mcu, i); > + if (ret) > + return dev_err_probe(&pdev->dev, ret, > + "failed to register error led %d\n", i); > + } > + > + if (variant->usb_led) { > + ret = qnap_mcu_register_usb_led(&pdev->dev, mcu); > + if (ret) > + return dev_err_probe(&pdev->dev, ret, > + "failed to register usb led %d\n", i); The 'i' here looks like a copy/paste error. > + } > + > + return 0; > +} > + > +static struct platform_driver qnap_mcu_leds_driver = { > + .probe = qnap_mcu_leds_probe, > + .driver = { > + .name = "qnap-mcu-leds", > + }, > +}; > +module_platform_driver(qnap_mcu_leds_driver); > + > +MODULE_ALIAS("platform:qnap-mcu-leds"); > +MODULE_AUTHOR("Heiko Stuebner "); > +MODULE_DESCRIPTION("QNAP MCU LEDs driver"); > +MODULE_LICENSE("GPL"); > -- > 2.43.0 > -- Lee Jones [李琼斯] 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 32FA6C83F2D for ; Thu, 29 Aug 2024 16:28:31 +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:In-Reply-To:MIME-Version:References: Message-ID:Subject:Cc:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=EzBfUvIz8wDpsq7WUmrddpj0Wwj18a6qBKPChGK0dR4=; b=DphoxqgapQknF9 eXvBXeerIYkev/quoiIrTQBWSpR6/3MSLEPFog9Srf7mjPjQXIuG5QDfKOND/Z3zq4WmvkNMs1/Jy DuXbhz5JMjWAjufYL20c40KV4oQeRPL/1atNueciLPLRjajr3cpGTILf864rElrMh3Y7AK6b1fswc AY9k7oxrrrNAKRWYqavJt0bUi1WVnjFE29oYrL3Jwzx6Y27MP0Kl/Z8fIvrFoduW4gtdXYZTv8A9k XMjUGwu/Iz/7NxJs8H8UdC1pHG4n49T0OQzrU1Qy5DOV0WQ8DpmKQvWCKPpLn+2qfk0+1d7cRYilL N1cLDPMU4fLeLJ0ZqNJw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sji0V-00000002pv7-0FeJ; Thu, 29 Aug 2024 16:28:23 +0000 Received: from nyc.source.kernel.org ([147.75.193.91]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sjhzN-00000002pg7-3C7H; Thu, 29 Aug 2024 16:27:15 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 9DF7FA404DA; Thu, 29 Aug 2024 16:27:05 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DD8BFC4CEC2; Thu, 29 Aug 2024 16:27:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724948832; bh=rUK7cYrfp3ANOIDU3rLaYOEYkyvnUKtRN7aNsL8GQDU=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=J3aSAJAmkUXpSwt1M+icllnaM5UhiPpzeCpja5FEKOILNoHE1faNT1islB9c6BLzx Zr7sVdo+BZ4PvsEmCsflfnl/qt3C5gEGlRvHzB7aZnS43ZI7rtlS009Xm50T1zpjS7 MsYc70pcCEDEQCWonNnsm73gyxnunmxfdf4vsX7Pf8t2XT5S/mYPo3/g9S/qBPhODn GTFv2MbII2PA9H8Gk3xTFxcEzSf+1rE3nhDSUhQEvpON0zhy0S85i1P4OjXiNKaw0m 6tB2Psy+e0FKIiWS5xvXYoKDy478U2Ao5kbQ82ypDGhDa6jj5mflzN35tq91Lsx2jO L2iAgG//6rHqw== Date: Thu, 29 Aug 2024 17:27:05 +0100 From: Lee Jones To: Heiko Stuebner Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, jdelvare@suse.com, linux@roeck-us.net, dmitry.torokhov@gmail.com, pavel@ucw.cz, ukleinek@debian.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-input@vger.kernel.org, linux-leds@vger.kernel.org Subject: Re: [PATCH v6 3/7] leds: add driver for LEDs from qnap-mcu devices Message-ID: <20240829162705.GR6858@google.com> References: <20240825203235.1122198-1-heiko@sntech.de> <20240825203235.1122198-4-heiko@sntech.de> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20240825203235.1122198-4-heiko@sntech.de> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240829_092713_964576_F90F6B2E X-CRM114-Status: GOOD ( 41.15 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org T24gU3VuLCAyNSBBdWcgMjAyNCwgSGVpa28gU3R1ZWJuZXIgd3JvdGU6Cgo+IFRoaXMgYWRkcyBh IGRyaXZlciB0aGF0IGNvbm5lY3RzIHRvIHRoZSBxbmFwLW1jdSBtZmQgZHJpdmVyIGFuZCBwcm92 aWRlcwo+IGFjY2VzcyB0byB0aGUgTEVEcyBvbiBpdC4KPiAKPiBTaWduZWQtb2ZmLWJ5OiBIZWlr byBTdHVlYm5lciA8aGVpa29Ac250ZWNoLmRlPgo+IC0tLQo+ICBNQUlOVEFJTkVSUyAgICAgICAg ICAgICAgICAgIHwgICAxICsKPiAgZHJpdmVycy9sZWRzL0tjb25maWcgICAgICAgICB8ICAxMSAr Kwo+ICBkcml2ZXJzL2xlZHMvTWFrZWZpbGUgICAgICAgIHwgICAxICsKPiAgZHJpdmVycy9sZWRz L2xlZHMtcW5hcC1tY3UuYyB8IDIyNiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr Kwo+ICA0IGZpbGVzIGNoYW5nZWQsIDIzOSBpbnNlcnRpb25zKCspCj4gIGNyZWF0ZSBtb2RlIDEw MDY0NCBkcml2ZXJzL2xlZHMvbGVkcy1xbmFwLW1jdS5jCj4gCj4gZGlmZiAtLWdpdCBhL01BSU5U QUlORVJTIGIvTUFJTlRBSU5FUlMKPiBpbmRleCAwZmJkMmQ5NTNkYTQuLjRkZmYwZTIzN2YyMiAx MDA2NDQKPiAtLS0gYS9NQUlOVEFJTkVSUwo+ICsrKyBiL01BSU5UQUlORVJTCj4gQEAgLTE4NjU3 LDYgKzE4NjU3LDcgQEAgRjoJZHJpdmVycy9tZWRpYS90dW5lcnMvcW0xZDFjMDA0MioKPiAgUU5B UCBNQ1UgRFJJVkVSCj4gIE06CUhlaWtvIFN0dWVibmVyIDxoZWlrb0BzbnRlY2guZGU+Cj4gIFM6 CU1haW50YWluZWQKPiArRjoJZHJpdmVycy9sZWRzL2xlZHMtcW5hcC1tY3UuYwo+ICBGOglkcml2 ZXJzL21mZC9xbmFwLW1jdS5jCj4gIEY6CWluY2x1ZGUvbGludXgvcW5hcC1tY3UuaAo+ICAKPiBk aWZmIC0tZ2l0IGEvZHJpdmVycy9sZWRzL0tjb25maWcgYi9kcml2ZXJzL2xlZHMvS2NvbmZpZwo+ IGluZGV4IDhkOWQ4ZGEzNzZlNC4uOWEzMzc0NzhkZDgwIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMv bGVkcy9LY29uZmlnCj4gKysrIGIvZHJpdmVycy9sZWRzL0tjb25maWcKPiBAQCAtNTgwLDYgKzU4 MCwxNyBAQCBjb25maWcgTEVEU19QQ0E5OTVYCj4gIAkgIExFRCBkcml2ZXIgY2hpcHMgYWNjZXNz ZWQgdmlhIHRoZSBJMkMgYnVzLiBTdXBwb3J0ZWQKPiAgCSAgZGV2aWNlcyBpbmNsdWRlIFBDQTk5 NTVCVFcsIFBDQTk5NTJUVyBhbmQgUENBOTk1NVRXLgo+ICAKPiArY29uZmlnIExFRFNfUU5BUF9N Q1UKPiArCXRyaXN0YXRlICJMRUQgU3VwcG9ydCBmb3IgUU5BUCBNQ1UgY29udHJvbGxlcnMiCj4g KwlkZXBlbmRzIG9uIExFRFNfQ0xBU1MKPiArCWRlcGVuZHMgb24gTUZEX1FOQVBfTUNVCj4gKwlo ZWxwCj4gKwkgIFRoaXMgb3B0aW9uIGVuYWJsZXMgc3VwcG9ydCBmb3IgTEVEcyBhdmFpbGFibGUg b24gZW1iZWRkZWQKPiArCSAgY29udHJvbGxlcnMgdXNlZCBpbiBRTkFQIE5BUyBkZXZpY2VzLgo+ ICsKPiArCSAgVGhpcyBkcml2ZXIgY2FuIGFsc28gYmUgYnVpbHQgYXMgYSBtb2R1bGUuIElmIHNv LCB0aGUgbW9kdWxlCj4gKwkgIHdpbGwgYmUgY2FsbGVkIHFuYXAtbWN1LWxlZHMuCj4gKwo+ICBj b25maWcgTEVEU19XTTgzMVhfU1RBVFVTCj4gIAl0cmlzdGF0ZSAiTEVEIHN1cHBvcnQgZm9yIHN0 YXR1cyBMRURzIG9uIFdNODMxeCBQTUlDcyIKPiAgCWRlcGVuZHMgb24gTEVEU19DTEFTUwo+IGRp ZmYgLS1naXQgYS9kcml2ZXJzL2xlZHMvTWFrZWZpbGUgYi9kcml2ZXJzL2xlZHMvTWFrZWZpbGUK PiBpbmRleCAxOGFmYmI1YTIzZWUuLmM2Zjc0ODY1ZDcyOSAxMDA2NDQKPiAtLS0gYS9kcml2ZXJz L2xlZHMvTWFrZWZpbGUKPiArKysgYi9kcml2ZXJzL2xlZHMvTWFrZWZpbGUKPiBAQCAtNzksNiAr NzksNyBAQCBvYmotJChDT05GSUdfTEVEU19QQ0E5OTVYKQkJKz0gbGVkcy1wY2E5OTV4Lm8KPiAg b2JqLSQoQ09ORklHX0xFRFNfUE04MDU4KQkJKz0gbGVkcy1wbTgwNTgubwo+ICBvYmotJChDT05G SUdfTEVEU19QT1dFUk5WKQkJKz0gbGVkcy1wb3dlcm52Lm8KPiAgb2JqLSQoQ09ORklHX0xFRFNf UFdNKQkJCSs9IGxlZHMtcHdtLm8KPiArb2JqLSQoQ09ORklHX0xFRFNfUU5BUF9NQ1UpCQkrPSBs ZWRzLXFuYXAtbWN1Lm8KPiAgb2JqLSQoQ09ORklHX0xFRFNfUkVHVUxBVE9SKQkJKz0gbGVkcy1y ZWd1bGF0b3Iubwo+ICBvYmotJChDT05GSUdfTEVEU19TQzI3WFhfQkxUQykJCSs9IGxlZHMtc2My N3h4LWJsdGMubwo+ICBvYmotJChDT05GSUdfTEVEU19TVU41MElfQTEwMCkJCSs9IGxlZHMtc3Vu NTBpLWExMDAubwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2xlZHMvbGVkcy1xbmFwLW1jdS5jIGIv ZHJpdmVycy9sZWRzL2xlZHMtcW5hcC1tY3UuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5k ZXggMDAwMDAwMDAwMDAwLi4wNzIzZWM1MmU0YzUKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJp dmVycy9sZWRzL2xlZHMtcW5hcC1tY3UuYwo+IEBAIC0wLDAgKzEsMjI2IEBACj4gKy8vIFNQRFgt TGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wLW9ubHkKPiArCgpTdXBlcmZsdW91cyBsaW5lLgoK PiArLyoKPiArICogRHJpdmVyIGZvciBMRURzIGZvdW5kIG9uIFFOQVAgTUNVIGRldmljZXMKPiAr ICoKPiArICogQ29weXJpZ2h0IChDKSAyMDI0IEhlaWtvIFN0dWVibmVyIDxoZWlrb0BzbnRlY2gu ZGU+Cj4gKyAqLwo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2xlZHMuaD4KPiArI2luY2x1ZGUgPGxp bnV4L21mZC9xbmFwLW1jdS5oPgo+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+Cj4gKyNpbmNs dWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2UuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4K PiArI2luY2x1ZGUgPHVhcGkvbGludXgvdWxlZHMuaD4KPiArCj4gK2VudW0gcW5hcF9tY3VfZXJy X2xlZF9tb2RlIHsKPiArCVFOQVBfTUNVX0VSUl9MRURfT04gPSAwLAo+ICsJUU5BUF9NQ1VfRVJS X0xFRF9PRkYgPSAxLAo+ICsJUU5BUF9NQ1VfRVJSX0xFRF9CTElOS19GQVNUID0gMiwKPiArCVFO QVBfTUNVX0VSUl9MRURfQkxJTktfU0xPVyA9IDMsCj4gK307Cj4gKwo+ICtzdHJ1Y3QgcW5hcF9t Y3VfZXJyX2xlZCB7Cj4gKwlzdHJ1Y3QgcW5hcF9tY3UgKm1jdTsKPiArCXN0cnVjdCBsZWRfY2xh c3NkZXYgY2RldjsKPiArCWNoYXIgbmFtZVtMRURfTUFYX05BTUVfU0laRV07Cj4gKwl1OCBudW07 Cj4gKwl1OCBtb2RlOwo+ICt9Owo+ICsKPiArc3RhdGljIGlubGluZSBzdHJ1Y3QgcW5hcF9tY3Vf ZXJyX2xlZCAqCj4gKwkJY2Rldl90b19xbmFwX21jdV9lcnJfbGVkKHN0cnVjdCBsZWRfY2xhc3Nk ZXYgKmxlZF9jZGV2KQo+ICt7Cj4gKwlyZXR1cm4gY29udGFpbmVyX29mKGxlZF9jZGV2LCBzdHJ1 Y3QgcW5hcF9tY3VfZXJyX2xlZCwgY2Rldik7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcW5hcF9t Y3VfZXJyX2xlZF9zZXQoc3RydWN0IGxlZF9jbGFzc2RldiAqbGVkX2NkZXYsCj4gKwkJCQllbnVt IGxlZF9icmlnaHRuZXNzIHZhbHVlKQoKJ3ZhbHVlJyBpcyBhIHRlcnJpYmxlIHZhcmlhYmxlIG5h bWUuCgpQbGVhc2UgZGVzY3JpYmUgdGhlIGRhdGEuICAnYnJpZ2h0bmVzcycgc2VlbXMgYXBwcm9w cmlhdGUuCgo+ICt7Cj4gKwlzdHJ1Y3QgcW5hcF9tY3VfZXJyX2xlZCAqZXJyX2xlZCA9IGNkZXZf dG9fcW5hcF9tY3VfZXJyX2xlZChsZWRfY2Rldik7Cj4gKwl1OCBjbWRbXSA9IHsgMHg0MCwgMHg1 MiwgMHgzMCArIGVycl9sZWQtPm51bSwgMHgzMCB9OwoKUmVhbGx5IG5vdCBmYW4gb2YgdGhlc2Ug bWFnaWMgdmFsdWVzIGJlaW5nIHVzZWQgcmF3IGxpa2UgdGhpcy4KCj4gKwkvKiBEb24ndCBkaXN0 dXJiIGEgcG9zc2libGUgc2V0IGJsaW5rLW1vZGUgaWYgTEVEIGlzIGFscmVhZHkgb24gKi8KCldo eSBub3Qgc2F2ZSBjeWNsZXMgYW5kIHJldHVybiBpZiBibGluayBtb2RlIGlzIGFscmVhZHkgZW5h YmxlZD8KCj4gKwlpZiAodmFsdWUgPT0gMCkKPiArCQllcnJfbGVkLT5tb2RlID0gUU5BUF9NQ1Vf RVJSX0xFRF9PRkY7Cj4gKwllbHNlIGlmIChlcnJfbGVkLT5tb2RlID09IFFOQVBfTUNVX0VSUl9M RURfT0ZGKQo+ICsJCWVycl9sZWQtPm1vZGUgPSBRTkFQX01DVV9FUlJfTEVEX09OOwoKVGhlbiB5 b3UgY2FuIGRvOgoKCWVycl9sZWQtPm1vZGUgPSB2YWx1ZSA/IFFOQVBfTUNVX0VSUl9MRURfT04g OiBRTkFQX01DVV9FUlJfTEVEX09GRjsKCj4gKwljbWRbM10gPSAweDMwICsgZXJyX2xlZC0+bW9k ZTsKPiArCj4gKwlyZXR1cm4gcW5hcF9tY3VfZXhlY193aXRoX2FjayhlcnJfbGVkLT5tY3UsIGNt ZCwgc2l6ZW9mKGNtZCkpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHFuYXBfbWN1X2Vycl9sZWRf Ymxpbmtfc2V0KHN0cnVjdCBsZWRfY2xhc3NkZXYgKmxlZF9jZGV2LAo+ICsJCQkJICAgICAgdW5z aWduZWQgbG9uZyAqZGVsYXlfb24sCj4gKwkJCQkgICAgICB1bnNpZ25lZCBsb25nICpkZWxheV9v ZmYpCj4gK3sKPiArCXN0cnVjdCBxbmFwX21jdV9lcnJfbGVkICplcnJfbGVkID0gY2Rldl90b19x bmFwX21jdV9lcnJfbGVkKGxlZF9jZGV2KTsKPiArCXU4IGNtZFtdID0geyAweDQwLCAweDUyLCAw eDMwICsgZXJyX2xlZC0+bnVtLCAweDMwIH07Cj4gKwo+ICsJLyogTEVEIGlzIG9mZiwgbm90aGlu ZyB0byBkbyAqLwo+ICsJaWYgKGVycl9sZWQtPm1vZGUgPT0gUU5BUF9NQ1VfRVJSX0xFRF9PRkYp Cj4gKwkJcmV0dXJuIDA7Cj4gKwo+ICsJaWYgKCpkZWxheV9vbiA8IDUwMCkgewoKU2V0dGluZyBk ZWxheV9vbiBiYXNlZCBvbiB0aGUgY3VycmVudCB2YWx1ZSBvZiBkZWxheV9vbiBzb3VuZHMgc2tl dGNoeS4KCj4gKwkJKmRlbGF5X29uID0gMTAwOwo+ICsJCSpkZWxheV9vZmYgPSAxMDA7Cj4gKwkJ ZXJyX2xlZC0+bW9kZSA9IFFOQVBfTUNVX0VSUl9MRURfQkxJTktfRkFTVDsKPiArCX0gZWxzZSB7 Cj4gKwkJKmRlbGF5X29uID0gNTAwOwo+ICsJCSpkZWxheV9vZmYgPSA1MDA7Cj4gKwkJZXJyX2xl ZC0+bW9kZSA9IFFOQVBfTUNVX0VSUl9MRURfQkxJTktfU0xPVzsKPiArCX0KCkhvdyBkbyB5b3Ug Y2hhbmdlIGZyb20gYSBmYXN0IHRvIGEgc2xvdyBibGlua2luZyBMRUQgYW5kIGJhY2sgYWdhaW4/ Cgo+ICsJY21kWzNdID0gMHgzMCArIGVycl9sZWQtPm1vZGU7Cj4gKwo+ICsJcmV0dXJuIHFuYXBf bWN1X2V4ZWNfd2l0aF9hY2soZXJyX2xlZC0+bWN1LCBjbWQsIHNpemVvZihjbWQpKTsKPiArfQo+ ICsKPiArc3RhdGljIGludCBxbmFwX21jdV9yZWdpc3Rlcl9lcnJfbGVkKHN0cnVjdCBkZXZpY2Ug KmRldiwgc3RydWN0IHFuYXBfbWN1ICptY3UsIGludCBudW0pCgpXaGF0J3MgbnVtPyAgSSBzaG91 bGQgYmUgYWJsZSB0byBhbnN3ZXIgdGhhdCBieSB0aGUgbm9tZW5jbGF0dXJlLgoKPiArewo+ICsJ c3RydWN0IHFuYXBfbWN1X2Vycl9sZWQgKmVycl9sZWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWVy cl9sZWQgPSBkZXZtX2t6YWxsb2MoZGV2LCBzaXplb2YoKmVycl9sZWQpLCBHRlBfS0VSTkVMKTsK PiArCWlmICghZXJyX2xlZCkKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwllcnJfbGVkLT5t Y3UgPSBtY3U7Cj4gKwllcnJfbGVkLT5udW0gPSBudW07Cj4gKwllcnJfbGVkLT5tb2RlID0gUU5B UF9NQ1VfRVJSX0xFRF9PRkY7Cj4gKwo+ICsJc25wcmludGYoZXJyX2xlZC0+bmFtZSwgTEVEX01B WF9OQU1FX1NJWkUsICJoZGQlZDpyZWQ6c3RhdHVzIiwgbnVtICsgMSk7CgpzY25wcmludGYoKT8K Cj4gKwllcnJfbGVkLT5jZGV2Lm5hbWUgPSBlcnJfbGVkLT5uYW1lOwo+ICsKPiArCWVycl9sZWQt PmNkZXYuYnJpZ2h0bmVzc19zZXRfYmxvY2tpbmcgPSBxbmFwX21jdV9lcnJfbGVkX3NldDsKPiAr CWVycl9sZWQtPmNkZXYuYmxpbmtfc2V0ID0gcW5hcF9tY3VfZXJyX2xlZF9ibGlua19zZXQ7Cj4g KwllcnJfbGVkLT5jZGV2LmJyaWdodG5lc3MgPSAwOwo+ICsJZXJyX2xlZC0+Y2Rldi5tYXhfYnJp Z2h0bmVzcyA9IDE7Cj4gKwo+ICsJcmV0ID0gZGV2bV9sZWRfY2xhc3NkZXZfcmVnaXN0ZXIoZGV2 LCAmZXJyX2xlZC0+Y2Rldik7Cj4gKwlpZiAocmV0KQo+ICsJCXJldHVybiBkZXZfZXJyX3Byb2Jl KGRldiwgcmV0LCAiZmFpbGVkIHRvIHJlZ2lzdGVyIGhkZCBsZWQgJWQiLCBudW0pOwoKIkhERCBM RUQiCgo+ICsJcmV0dXJuIHFuYXBfbWN1X2Vycl9sZWRfc2V0KCZlcnJfbGVkLT5jZGV2LCAwKTsK PiArfQo+ICsKPiArZW51bSBxbmFwX21jdV91c2JfbGVkX21vZGUgewo+ICsJUU5BUF9NQ1VfVVNC X0xFRF9PTiA9IDEsCj4gKwlRTkFQX01DVV9VU0JfTEVEX09GRiA9IDMsCj4gKwlRTkFQX01DVV9V U0JfTEVEX0JMSU5LID0gMiwKPiArfTsKPiArCj4gK3N0cnVjdCBxbmFwX21jdV91c2JfbGVkIHsK PiArCXN0cnVjdCBxbmFwX21jdSAqbWN1Owo+ICsJc3RydWN0IGxlZF9jbGFzc2RldiBjZGV2Owo+ ICsJdTggbW9kZTsKPiArfTsKPiArCj4gK3N0YXRpYyBpbmxpbmUgc3RydWN0IHFuYXBfbWN1X3Vz Yl9sZWQgKgo+ICsJCWNkZXZfdG9fcW5hcF9tY3VfdXNiX2xlZChzdHJ1Y3QgbGVkX2NsYXNzZGV2 ICpsZWRfY2RldikKPiArewo+ICsJcmV0dXJuIGNvbnRhaW5lcl9vZihsZWRfY2Rldiwgc3RydWN0 IHFuYXBfbWN1X3VzYl9sZWQsIGNkZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHFuYXBfbWN1 X3VzYl9sZWRfc2V0KHN0cnVjdCBsZWRfY2xhc3NkZXYgKmxlZF9jZGV2LAo+ICsJCQkJZW51bSBs ZWRfYnJpZ2h0bmVzcyB2YWx1ZSkKPiArewo+ICsJc3RydWN0IHFuYXBfbWN1X3VzYl9sZWQgKnVz Yl9sZWQgPSBjZGV2X3RvX3FuYXBfbWN1X3VzYl9sZWQobGVkX2NkZXYpOwo+ICsJdTggY21kW10g PSB7IDB4NDAsIDB4NDMsIDAgfTsKPiArCj4gKwkvKgo+ICsJICogSWYgdGhlIGxlZCBpcyBvZmYs IHR1cm4gaXQgb24uIE90aGVyd2lzZSBkb24ndCBkaXN0dXJiCgoiTEVEIgoKPiArCSAqIGEgcG9z c2libGUgc2V0IGJsaW5rLW1vZGUuCj4gKwkgKi8KPiArCWlmICh2YWx1ZSA9PSAwKQo+ICsJCXVz Yl9sZWQtPm1vZGUgPSBRTkFQX01DVV9VU0JfTEVEX09GRjsKPiArCWVsc2UgaWYgKHVzYl9sZWQt Pm1vZGUgPT0gUU5BUF9NQ1VfVVNCX0xFRF9PRkYpCj4gKwkJdXNiX2xlZC0+bW9kZSA9IFFOQVBf TUNVX1VTQl9MRURfT047CgpTYW1lIHN1Z2dlc3Rpb25zIGFzIGFib3ZlLgoKPiArCS8qIGJ5dGUg MyBpcyBzaGFyZWQgYmV0d2VlbiB0aGUgdXNiIGxlZCB0YXJnZXQgYW5kIHNldHRpbmcgdGhlIG1v ZGUgKi8KCiJCeXRlIiBmb3IgdHdvIHJlYXNvbnMuICBGaXJzdGx5IGJlY2F1c2UgaXQncyB0aGUg Y29ycmVjdCBjYXBpdGFsaXNhdGlvbgpvZiBCeXRlIGFuZCBzZWNvbmRseSBiZWNhdXNlIGl0J3Mg dGhlIHN0YXJ0IG9mIGEgc2VudGVuY2UuCgoiVVNCIiBhbmQgIkxFRCIgdGhyb3VnaG91dCBwbGVh c2UuCgo+ICsJY21kWzJdID0gMHg0NCB8IHVzYl9sZWQtPm1vZGU7Cj4gKwo+ICsJcmV0dXJuIHFu YXBfbWN1X2V4ZWNfd2l0aF9hY2sodXNiX2xlZC0+bWN1LCBjbWQsIHNpemVvZihjbWQpKTsKPiAr fQo+ICsKPiArc3RhdGljIGludCBxbmFwX21jdV91c2JfbGVkX2JsaW5rX3NldChzdHJ1Y3QgbGVk X2NsYXNzZGV2ICpsZWRfY2RldiwKPiArCQkJCSAgICAgIHVuc2lnbmVkIGxvbmcgKmRlbGF5X29u LAo+ICsJCQkJICAgICAgdW5zaWduZWQgbG9uZyAqZGVsYXlfb2ZmKQo+ICt7Cj4gKwlzdHJ1Y3Qg cW5hcF9tY3VfdXNiX2xlZCAqdXNiX2xlZCA9IGNkZXZfdG9fcW5hcF9tY3VfdXNiX2xlZChsZWRf Y2Rldik7Cj4gKwl1OCBjbWRbXSA9IHsgMHg0MCwgMHg0MywgMCB9Owo+ICsKPiArCS8qIExFRCBp cyBvZmYsIG5vdGhpbmcgdG8gZG8gKi8KPiArCWlmICh1c2JfbGVkLT5tb2RlID09IFFOQVBfTUNV X1VTQl9MRURfT0ZGKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCSpkZWxheV9vbiA9IDI1MDsKPiAr CSpkZWxheV9vZmYgPSAyNTA7Cj4gKwl1c2JfbGVkLT5tb2RlID0gUU5BUF9NQ1VfVVNCX0xFRF9C TElOSzsKPiArCj4gKwkvKiBieXRlIDMgaXMgc2hhcmVkIGJldHdlZW4gdGhlIHVzYiBsZWQgdGFy Z2V0IGFuZCBzZXR0aW5nIHRoZSBtb2RlICovCj4gKwljbWRbMl0gPSAweDQ0IHwgdXNiX2xlZC0+ bW9kZTsKPiArCj4gKwlyZXR1cm4gcW5hcF9tY3VfZXhlY193aXRoX2Fjayh1c2JfbGVkLT5tY3Us IGNtZCwgc2l6ZW9mKGNtZCkpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHFuYXBfbWN1X3JlZ2lz dGVyX3VzYl9sZWQoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgcW5hcF9tY3UgKm1jdSkKPiAr ewo+ICsJc3RydWN0IHFuYXBfbWN1X3VzYl9sZWQgKnVzYl9sZWQ7Cj4gKwlpbnQgcmV0Owo+ICsK PiArCXVzYl9sZWQgPSBkZXZtX2t6YWxsb2MoZGV2LCBzaXplb2YoKnVzYl9sZWQpLCBHRlBfS0VS TkVMKTsKPiArCWlmICghdXNiX2xlZCkKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwl1c2Jf bGVkLT5tY3UgPSBtY3U7Cj4gKwl1c2JfbGVkLT5tb2RlID0gUU5BUF9NQ1VfVVNCX0xFRF9PRkY7 Cj4gKwl1c2JfbGVkLT5jZGV2Lm5hbWUgPSAidXNiOmJsdWU6ZGlzayI7Cj4gKwl1c2JfbGVkLT5j ZGV2LmJyaWdodG5lc3Nfc2V0X2Jsb2NraW5nID0gcW5hcF9tY3VfdXNiX2xlZF9zZXQ7Cj4gKwl1 c2JfbGVkLT5jZGV2LmJsaW5rX3NldCA9IHFuYXBfbWN1X3VzYl9sZWRfYmxpbmtfc2V0Owo+ICsJ dXNiX2xlZC0+Y2Rldi5icmlnaHRuZXNzID0gMDsKPiArCXVzYl9sZWQtPmNkZXYubWF4X2JyaWdo dG5lc3MgPSAxOwo+ICsKPiArCXJldCA9IGRldm1fbGVkX2NsYXNzZGV2X3JlZ2lzdGVyKGRldiwg JnVzYl9sZWQtPmNkZXYpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gZGV2X2Vycl9wcm9iZShk ZXYsIHJldCwgImZhaWxlZCB0byByZWdpc3RlciB1c2IgbGVkIik7Cj4gKwo+ICsJcmV0dXJuIHFu YXBfbWN1X3VzYl9sZWRfc2V0KCZ1c2JfbGVkLT5jZGV2LCAwKTsKPiArfQo+ICsKPiArc3RhdGlj IGludCBxbmFwX21jdV9sZWRzX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4g K3sKPiArCXN0cnVjdCBxbmFwX21jdSAqbWN1ID0gZGV2X2dldF9kcnZkYXRhKHBkZXYtPmRldi5w YXJlbnQpOwo+ICsJY29uc3Qgc3RydWN0IHFuYXBfbWN1X3ZhcmlhbnQgKnZhcmlhbnQgPSBxbmFw X21jdV9nZXRfdmFyaWFudF9kYXRhKG1jdSk7CgpHcmFiIHRoaXMgZnJvbSBwbGF0Zm9ybV9kYXRh LgoKPiArCWludCByZXQsIGk7Cj4gKwo+ICsJZm9yIChpID0gMDsgaSA8IHZhcmlhbnQtPm51bV9k cml2ZXM7IGkrKykgewoKWW91IGNhbiB1c2U6CgoJZm9yIChpbnQgaSA9IDA7IC4uCgo+ICsJCXJl dCA9IHFuYXBfbWN1X3JlZ2lzdGVyX2Vycl9sZWQoJnBkZXYtPmRldiwgbWN1LCBpKTsKPiArCQlp ZiAocmV0KQo+ICsJCQlyZXR1cm4gZGV2X2Vycl9wcm9iZSgmcGRldi0+ZGV2LCByZXQsCj4gKwkJ CQkJImZhaWxlZCB0byByZWdpc3RlciBlcnJvciBsZWQgJWRcbiIsIGkpOwo+ICsJfQo+ICsKPiAr CWlmICh2YXJpYW50LT51c2JfbGVkKSB7Cj4gKwkJcmV0ID0gcW5hcF9tY3VfcmVnaXN0ZXJfdXNi X2xlZCgmcGRldi0+ZGV2LCBtY3UpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJldHVybiBkZXZfZXJy X3Byb2JlKCZwZGV2LT5kZXYsIHJldCwKPiArCQkJCQkiZmFpbGVkIHRvIHJlZ2lzdGVyIHVzYiBs ZWQgJWRcbiIsIGkpOwoKVGhlICdpJyBoZXJlIGxvb2tzIGxpa2UgYSBjb3B5L3Bhc3RlIGVycm9y LgoKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHN0cnVjdCBwbGF0 Zm9ybV9kcml2ZXIgcW5hcF9tY3VfbGVkc19kcml2ZXIgPSB7Cj4gKwkucHJvYmUgPSBxbmFwX21j dV9sZWRzX3Byb2JlLAo+ICsJLmRyaXZlciA9IHsKPiArCQkubmFtZSA9ICJxbmFwLW1jdS1sZWRz IiwKPiArCX0sCj4gK307Cj4gK21vZHVsZV9wbGF0Zm9ybV9kcml2ZXIocW5hcF9tY3VfbGVkc19k cml2ZXIpOwo+ICsKPiArTU9EVUxFX0FMSUFTKCJwbGF0Zm9ybTpxbmFwLW1jdS1sZWRzIik7Cj4g K01PRFVMRV9BVVRIT1IoIkhlaWtvIFN0dWVibmVyIDxoZWlrb0BzbnRlY2guZGU+Iik7Cj4gK01P RFVMRV9ERVNDUklQVElPTigiUU5BUCBNQ1UgTEVEcyBkcml2ZXIiKTsKPiArTU9EVUxFX0xJQ0VO U0UoIkdQTCIpOwo+IC0tIAo+IDIuNDMuMAo+IAoKLS0gCkxlZSBKb25lcyBb5p2O55C85pavXQoK X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTGludXgtcm9j a2NoaXAgbWFpbGluZyBsaXN0CkxpbnV4LXJvY2tjaGlwQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0 cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1yb2NrY2hpcAo=