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 X-Spam-Level: X-Spam-Status: No, score=-8.3 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 59E15C433DF for ; Tue, 9 Jun 2020 15:01:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2194320774 for ; Tue, 9 Jun 2020 15:01:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=xs4all.nl header.i=@xs4all.nl header.b="Mx2FYbRZ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730698AbgFIPB5 (ORCPT ); Tue, 9 Jun 2020 11:01:57 -0400 Received: from lb1-smtp-cloud7.xs4all.net ([194.109.24.24]:39033 "EHLO lb1-smtp-cloud7.xs4all.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730654AbgFIPBx (ORCPT ); Tue, 9 Jun 2020 11:01:53 -0400 Received: from cust-b5b5937f ([IPv6:fc0c:c16d:66b8:757f:c639:739b:9d66:799d]) by smtp-cloud7.xs4all.net with ESMTPA id ifkujUBrRNp2zifkyjlyoh; Tue, 09 Jun 2020 17:01:46 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xs4all.nl; s=s1; t=1591714906; bh=2UBNyGiGQ39Gr5fhoeQ/g57it7qDzgt8h68l+Yh7uSo=; h=Subject:To:From:Message-ID:Date:MIME-Version:Content-Type:From: Subject; b=Mx2FYbRZ9Yk0KQkpbkJXXOr/ejLeJgWwYxEZVMLNU2ZVBbowF1vsVBJhBrxQv4h7c 9zxWCkXN0jm8oZyBP4rpUK2hsQLou8QEyC7hIU/j96EtewPOGsop5pcL5WVTwDIVsi asdd0YDwWrygf8syA8IFp92IRa70/6QrUZTGdfuKXijUKGlsSEVaFXR1qOZjgyZbsZ vB8Yh/RkUm7bJ3cG/0zPEicb8A0W3xBnHZK/H4e3qfZC/VnzFoFavz12UDW0ZKB48o n8ftC6RKwv6mENii0BFISk1cylWH178VJ8PLDTxBaVodt5Mph97X82HcL6411qWz7s lkFMxvy/UBnnA== Subject: Re: [PATCH v2 2/2] media: v4l: xilinx: Add Xilinx UHD-SDI Rx Subsystem driver To: Vishal Sagar , Hyun Kwon , "laurent.pinchart@ideasonboard.com" , "mchehab@kernel.org" , "robh+dt@kernel.org" , "mark.rutland@arm.com" , Michal Simek , "linux-media@vger.kernel.org" , "devicetree@vger.kernel.org" , "hans.verkuil@cisco.com" , "linux-arm-kernel@lists.infradead.org" , "linux-kernel@vger.kernel.org" , Dinesh Kumar , Sandip Kothari , Joe Perches References: <20200429141705.18755-1-vishal.sagar@xilinx.com> <20200429141705.18755-3-vishal.sagar@xilinx.com> <368b7efb-3faf-bb71-2bd0-826f2ab031e6@xs4all.nl> From: Hans Verkuil Message-ID: <7cecf608-a001-5986-8792-35c312dcc961@xs4all.nl> Date: Tue, 9 Jun 2020 17:01:36 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit X-CMAE-Envelope: MS4wfHwnUPLBZOiuFRgK7hI0kI2yqt/Chzc6XqbOErlzI+r7NrM+eNruttGZxWbmLQqP6U8jINREpscVwCksOA5A/z06kT/x2FZKm6r0HWqD5LxpJ5iQjnHW CNMz2qh0nEhuR56A+Y9MuGSdVt9Ch9fu9HlmNwX84/QQ5Ro0Di9ZrAq3g04WpHbznJpIl05aPwGve/OLmhlP41f35a+ftxkf93cF6ggH7j2DV9Us0gs1Gnop xqkRL6tCNaCq3F1XAdb3+UMjyGZiRzUSKfWNGIi1mrtzPVlSx94C+hBxCYXHqfu0bn3V+G3XurXEL2ElqGpadQy9UTtiJdJSrhoTSdcyMDDYvECd1J8csdZo 2KmmZE8Uzwhji0IGqzENkUsMNPIhBFXEetVUV2PJGaWT9Vw5K06qTZvRKM+jqNbgk0KDZAajIpo+tracnFfgglqmGA3yew4ip2bmXxmlOWLsq5UDzYUqYnbD XhNsdS97MFGX2hSKK9IrtePr7bR7I2nx4txKpwYUXBF/vJ4VZzuoTd2cveIEjqXHEl2X9T/bn1virLd7Wd6Lt7r/YUt5X0xEUfinirCMjEwOyT/D0J2fEZjX jFcdeBNXc7wjDD1Oz9E200Q04IZ0zn8FKqWxZDKl57H8I1VSKJhcMIlw2ZoNVa0/kko= Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 01/06/2020 16:59, Vishal Sagar wrote: > Hi Hans, > > Thanks for reviewing! > >> -----Original Message----- >> From: Hans Verkuil >> Sent: Wednesday, May 6, 2020 3:25 PM >> To: Vishal Sagar ; Hyun Kwon ; >> laurent.pinchart@ideasonboard.com; mchehab@kernel.org; >> robh+dt@kernel.org; mark.rutland@arm.com; Michal Simek >> ; linux-media@vger.kernel.org; >> devicetree@vger.kernel.org; hans.verkuil@cisco.com; linux-arm- >> kernel@lists.infradead.org; linux-kernel@vger.kernel.org; Dinesh Kumar >> ; Sandip Kothari ; Joe Perches >> >> Subject: Re: [PATCH v2 2/2] media: v4l: xilinx: Add Xilinx UHD-SDI Rx Subsystem >> driver >> >> Hi Vishal, >> >> Thank you for this patch. >> >> I have some comments below: >> >> On 29/04/2020 16:17, Vishal Sagar wrote: >>> The Xilinx UHD-SDI Rx subsystem soft IP is used to capture native SDI >>> streams from SDI sources like SDI broadcast equipment like cameras and >>> mixers. This block outputs either native SDI, native video or >>> AXI4-Stream compliant data stream for further processing. Please refer >>> to PG290 for details. >>> >>> The driver is used to configure the IP to add framer, search for >>> specific modes, get the detected mode, stream parameters, errors, etc. >>> It also generates events for video lock/unlock, bridge over/under flow. >>> >>> The driver supports 10/12 bpc YUV 422 media bus format currently. It also >>> decodes the stream parameters based on the ST352 packet embedded in the >>> stream. In case the ST352 packet isn't present in the stream, the core's >>> detected properties are used to set stream properties. >>> >>> The driver currently supports only the AXI4-Stream IP configuration. >>> >>> Signed-off-by: Vishal Sagar >>> --- >>> +/** >>> + * xsdirxss_set_format - This is used to set the pad format >>> + * @sd: Pointer to V4L2 Sub device structure >>> + * @cfg: Pointer to sub device pad information structure >>> + * @fmt: Pointer to pad level media bus format >>> + * >>> + * This function is used to set the pad format. >>> + * Since the pad format is fixed in hardware, it can't be >>> + * modified on run time. >>> + * >>> + * Return: 0 on success >>> + */ >>> +static int xsdirxss_set_format(struct v4l2_subdev *sd, >>> + struct v4l2_subdev_pad_config *cfg, >>> + struct v4l2_subdev_format *fmt) >>> +{ >>> + struct v4l2_mbus_framefmt *__format; >>> + struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd); >>> + >>> + dev_dbg(xsdirxss->core.dev, >>> + "set width %d height %d code %d field %d colorspace %d\n", >>> + fmt->format.width, fmt->format.height, >>> + fmt->format.code, fmt->format.field, >>> + fmt->format.colorspace); >>> + >>> + __format = __xsdirxss_get_pad_format(xsdirxss, cfg, >>> + fmt->pad, fmt->which); >>> + >>> + /* Currently reset the code to one fixed in hardware */ >>> + /* TODO : Add checks for width height */ >>> + fmt->format.code = __format->code; >> >> It should fill in the width and height based on the current DV timings. >> Ditto for the field (I assume that's fixed as well based on whether this >> is interlaced or not). I'm not sure how colorspace information is handled >> for SDI. >> > > Yes. I will update this logic to update the width, height and field based on current DV timings. > Please have a look at this in the next version. > The current IP supports BT709 colorimetry. > The colorimetry information of incoming stream is present in the ST 352 payload Byte 3 (bit 5 and bit 4) as per SMPTE ST 2081-10:2018. > B5:4 = 0 -> BT 709 as per SMPTE ST 274 OK, so this can be filled in by the driver as well. > >>> + >>> + return 0; >>> +} >>> + >>> +/** >>> + * xsdirxss_enum_mbus_code - Handle pixel format enumeration >>> + * @sd: pointer to v4l2 subdev structure >>> + * @cfg: V4L2 subdev pad configuration >>> + * @code: pointer to v4l2_subdev_mbus_code_enum structure >>> + * >>> + * Return: -EINVAL or zero on success >>> + */ >>> +static int xsdirxss_enum_mbus_code(struct v4l2_subdev *sd, >>> + struct v4l2_subdev_pad_config *cfg, >>> + struct v4l2_subdev_mbus_code_enum >> *code) >>> +{ >>> + struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd); >>> + u32 index = code->index; >>> + u32 maxindex; >>> + >>> + if (xsdirxss->core.bpc == 10) >>> + maxindex = ARRAY_SIZE(xsdirxss_10bpc_mbus_fmts); >>> + else >>> + maxindex = ARRAY_SIZE(xsdirxss_12bpc_mbus_fmts); >>> + >>> + if (code->pad || index >= maxindex) >>> + return -EINVAL; >>> + >>> + if (xsdirxss->core.bpc == 10) >>> + code->code = xsdirxss_10bpc_mbus_fmts[index]; >>> + else >>> + code->code = xsdirxss_12bpc_mbus_fmts[index]; >>> + >>> + return 0; >>> +} >>> + >>> +/** >>> + * xsdirxss_enum_dv_timings: Enumerate all the supported DV timings >>> + * @sd: pointer to v4l2 subdev structure >>> + * @timings: DV timings structure to be returned. >>> + * >>> + * Return: -EINVAL incase of invalid index and pad or zero on success >>> + */ >>> +static int xsdirxss_enum_dv_timings(struct v4l2_subdev *sd, >>> + struct v4l2_enum_dv_timings *timings) >>> +{ >>> + if (timings->index >= ARRAY_SIZE(fmt_cap)) >>> + return -EINVAL; >>> + >>> + if (timings->pad != 0) >>> + return -EINVAL; >>> + >>> + timings->timings = fmt_cap[timings->index]; >>> + return 0; >>> +} >>> + >>> +/** >>> + * xsdirxss_query_dv_timings: Query for the current DV timings >>> + * @sd: pointer to v4l2 subdev structure >>> + * @timings: DV timings structure to be returned. >>> + * >>> + * Return: -ENOLCK when video is not locked, -ERANGE when corresponding >> timing >>> + * entry is not found or zero on success. >>> + */ >>> +static int xsdirxss_query_dv_timings(struct v4l2_subdev *sd, >>> + struct v4l2_dv_timings *timings) >>> +{ >>> + struct xsdirxss_state *state = to_xsdirxssstate(sd); >>> + unsigned int i; >>> + >>> + if (!state->vidlocked) >>> + return -ENOLCK; >>> + >>> + for (i = 0; i < ARRAY_SIZE(xsdirxss_dv_timings); i++) { >>> + if (state->format.width == xsdirxss_dv_timings[i].width && >>> + state->format.height == xsdirxss_dv_timings[i].height && >>> + state->frame_interval.denominator == >>> + (xsdirxss_dv_timings[i].fps * 1000)) { >>> + *timings = xsdirxss_dv_timings[i].format; >>> + return 0; >>> + } >>> + } >>> + >>> + return -ERANGE; >>> +} >>> + >>> +/* ----------------------------------------------------------------------------- >>> + * Media Operations >>> + */ >>> + >>> +static const struct media_entity_operations xsdirxss_media_ops = { >>> + .link_validate = v4l2_subdev_link_validate >>> +}; >>> + >>> +static const struct v4l2_ctrl_ops xsdirxss_ctrl_ops = { >>> + .g_volatile_ctrl = xsdirxss_g_volatile_ctrl, >>> + .s_ctrl = xsdirxss_s_ctrl >>> +}; >>> + >>> +static const struct v4l2_ctrl_config xsdirxss_edh_ctrls[] = { >>> + { >>> + .ops = &xsdirxss_ctrl_ops, >>> + .id = V4L2_CID_XILINX_SDIRX_EDH_ERRCNT_ENABLE, >>> + .name = "SDI Rx : EDH Error Count Enable", >>> + .type = V4L2_CTRL_TYPE_BITMASK, >>> + .min = 0, >>> + .max = XSDIRX_EDH_ALLERR_MASK, >>> + .def = 0, >>> + }, { >>> + .ops = &xsdirxss_ctrl_ops, >>> + .id = V4L2_CID_XILINX_SDIRX_EDH_ERRCNT, >>> + .name = "SDI Rx : EDH Error Count", >>> + .type = V4L2_CTRL_TYPE_INTEGER, >>> + .min = 0, >>> + .max = 0xFFFF, >>> + .step = 1, >>> + .def = 0, >>> + .flags = V4L2_CTRL_FLAG_VOLATILE | >> V4L2_CTRL_FLAG_READ_ONLY, >>> + }, { >>> + .ops = &xsdirxss_ctrl_ops, >>> + .id = V4L2_CID_XILINX_SDIRX_EDH_STATUS, >>> + .name = "SDI Rx : EDH Status", >>> + .type = V4L2_CTRL_TYPE_INTEGER, >>> + .min = 0, >>> + .max = 0xFFFFFFFF, >>> + .step = 1, >>> + .def = 0, >>> + .flags = V4L2_CTRL_FLAG_VOLATILE | >> V4L2_CTRL_FLAG_READ_ONLY, >>> + } >>> +}; >>> + >>> +static const struct v4l2_ctrl_config xsdirxss_ctrls[] = { >>> + { >>> + .ops = &xsdirxss_ctrl_ops, >>> + .id = V4L2_CID_XILINX_SDIRX_FRAMER, >>> + .name = "SDI Rx : Enable Framer", >>> + .type = V4L2_CTRL_TYPE_BOOLEAN, >>> + .min = false, >>> + .max = true, >>> + .step = 1, >>> + .def = true, >>> + }, { >>> + .ops = &xsdirxss_ctrl_ops, >>> + .id = V4L2_CID_XILINX_SDIRX_VIDLOCK_WINDOW, >>> + .name = "SDI Rx : Video Lock Window", >>> + .type = V4L2_CTRL_TYPE_INTEGER, >>> + .min = 0, >>> + .max = 0xFFFFFFFF, >>> + .step = 1, >>> + .def = XSDIRX_DEFAULT_VIDEO_LOCK_WINDOW, >>> + }, { >>> + .ops = &xsdirxss_ctrl_ops, >>> + .id = V4L2_CID_XILINX_SDIRX_SEARCH_MODES, >>> + .name = "SDI Rx : Modes search Mask", >>> + .type = V4L2_CTRL_TYPE_BITMASK, >>> + .min = 0, >>> + .max = XSDIRX_DETECT_ALL_MODES, >>> + .def = XSDIRX_DETECT_ALL_MODES, >>> + }, { >>> + .ops = &xsdirxss_ctrl_ops, >>> + .id = V4L2_CID_XILINX_SDIRX_MODE_DETECT, >>> + .name = "SDI Rx : Mode Detect Status", >>> + .type = V4L2_CTRL_TYPE_INTEGER, >>> + .min = XSDIRX_MODE_SD_OFFSET, >>> + .max = XSDIRX_MODE_12GF_OFFSET, >>> + .step = 1, >>> + .flags = V4L2_CTRL_FLAG_VOLATILE | >> V4L2_CTRL_FLAG_READ_ONLY, >>> + }, { >>> + .ops = &xsdirxss_ctrl_ops, >>> + .id = V4L2_CID_XILINX_SDIRX_CRC, >>> + .name = "SDI Rx : CRC Error status", >>> + .type = V4L2_CTRL_TYPE_INTEGER, >>> + .min = 0, >>> + .max = 0xFFFFFFFF, >>> + .step = 1, >>> + .def = 0, >>> + .flags = V4L2_CTRL_FLAG_VOLATILE | >> V4L2_CTRL_FLAG_READ_ONLY, >>> + }, { >>> + .ops = &xsdirxss_ctrl_ops, >>> + .id = V4L2_CID_XILINX_SDIRX_TS_IS_INTERLACED, >>> + .name = "SDI Rx : TS is Interlaced", >>> + .type = V4L2_CTRL_TYPE_BOOLEAN, >>> + .min = false, >>> + .max = true, >>> + .def = false, >>> + .step = 1, >>> + .flags = V4L2_CTRL_FLAG_VOLATILE | >> V4L2_CTRL_FLAG_READ_ONLY, >>> + }, { >>> + .ops = &xsdirxss_ctrl_ops, >>> + .id = V4L2_CID_XILINX_SDIRX_ACTIVE_STREAMS, >>> + .name = "SDI Rx : Active Streams", >>> + .type = V4L2_CTRL_TYPE_INTEGER, >>> + .min = 1, >>> + .max = 16, >>> + .def = 1, >>> + .step = 1, >>> + .flags = V4L2_CTRL_FLAG_VOLATILE | >> V4L2_CTRL_FLAG_READ_ONLY, >>> + }, { >>> + .ops = &xsdirxss_ctrl_ops, >>> + .id = V4L2_CID_XILINX_SDIRX_IS_3GB, >>> + .name = "SDI Rx : Is 3GB", >>> + .type = V4L2_CTRL_TYPE_BOOLEAN, >>> + .min = false, >>> + .max = true, >>> + .def = false, >>> + .step = 1, >>> + .flags = V4L2_CTRL_FLAG_VOLATILE | >> V4L2_CTRL_FLAG_READ_ONLY, >>> + } >> >> All these controls need to be documented in the header. Some of these controls >> may turn out to be controls that can be standardized for SDI receivers, others >> might be more vendor or driver specific. >> > > I have documented these in the header. But it seems insufficient. Let me add more info in it. > Most of this is IP specific. Probably Mode detected and Active streams can be standardized. I'll review this some more when v3 is posted. It's likely I'll discuss this some more with you. > >>> +}; >>> + >>> +static const struct v4l2_subdev_core_ops xsdirxss_core_ops = { >>> + .log_status = xsdirxss_log_status, >>> + .subscribe_event = xsdirxss_subscribe_event, >>> + .unsubscribe_event = xsdirxss_unsubscribe_event >>> +}; >>> + >>> +static const struct v4l2_subdev_video_ops xsdirxss_video_ops = { >>> + .g_frame_interval = xsdirxss_g_frame_interval, >>> + .s_stream = xsdirxss_s_stream, >>> + .g_input_status = xsdirxss_g_input_status, >>> + .query_dv_timings = xsdirxss_query_dv_timings, >> >> This is missing g/s_dv_timings. You need to keep track of the current >> timings in the driver state: typically userspace will query timings and >> if that returns valid timings it will set them (s_dv_timings). With >> g_dv_timings the last set timings are returned. >> > > Thanks for sharing this information. I didn't get the sequence from the current documentation. > Let me know if there is a standard application that I may refer to for this. v4l2-ctl does this, actually. streaming_set_cap() in v4l2-ctl-streaming.cpp is what is used when you run 'v4l2-ctl --stream-mmap'. > >> If the timings change then the driver stops streaming and reports the >> SOURCE_CHANGE event, at which point userspace will query the new timings. >> > > The SOURCE_CHANGE event will be generated only after stopping the streaming to the downstream by > disabling the bridges. The core will always be enabled to detect any other incoming stream. > Once a new incoming stream is detected for video_lock_window amount of time, a video lock interrupt occurs. I don't quite understand this. The SOURCE_CHANGE event should be issued when the driver detects that it lost signal, or a new signal appears, or the stream changes resolution. I.e. all cases where userspace needs to take action. > >> The reported mediabus format resolution only changes when s_dv_timings >> is called: it's updated with the new width/height info. >> > > I will create another v4l2_mbus_framefmt member in the state structure which will be updated with the detected formats in the s_dv_timings. > Then application may call get/set_fmt(). > >> In other words: the timings reported by g_dv_timings are controlled by >> userspace, the timings reported by query_dv_timings reflect the actual >> timings received on the SDI bus. >> > > Thanks for this detailed explanation. 😊 > >>> +}; >>> + >>> +static const struct v4l2_subdev_pad_ops xsdirxss_pad_ops = { >>> + .init_cfg = xsdirxss_init_cfg, >>> + .get_fmt = xsdirxss_get_format, >>> + .set_fmt = xsdirxss_set_format, >>> + .enum_mbus_code = xsdirxss_enum_mbus_code, >>> + .enum_dv_timings = xsdirxss_enum_dv_timings, >> >> This is missing dv_timings_cap. >> > > I will add this in the next version. > >>> +}; >>> + >>> +static const struct v4l2_subdev_ops xsdirxss_ops = { >>> + .core = &xsdirxss_core_ops, >>> + .video = &xsdirxss_video_ops, >>> + .pad = &xsdirxss_pad_ops >>> +}; >>> + >>> +/* ----------------------------------------------------------------------------- >>> + * Platform Device Driver >>> + */ >>> + >>> +static int xsdirxss_parse_of(struct xsdirxss_state *xsdirxss) >>> +{ >>> + struct device_node *node = xsdirxss->core.dev->of_node; >>> + struct xsdirxss_core *core = &xsdirxss->core; >>> + struct device *dev = core->dev; >>> + struct fwnode_handle *ep, *rep; >>> + int ret; >>> + const char *sdi_std; >>> + >>> + core->include_edh = of_property_read_bool(node, "xlnx,include-edh"); >>> + dev_dbg(dev, "EDH property = %s\n", >>> + core->include_edh ? "Present" : "Absent"); >>> + >>> + ret = of_property_read_string(node, "xlnx,line-rate", &sdi_std); >>> + if (ret < 0) { >>> + dev_err(dev, "xlnx,line-rate property not found\n"); >>> + return ret; >>> + } >>> + >>> + if (!strncmp(sdi_std, "12G_SDI_8DS", XSDIRX_MAX_STR_LENGTH)) { >>> + core->mode = XSDIRXSS_SDI_STD_12G_8DS; >>> + } else if (!strncmp(sdi_std, "6G_SDI", XSDIRX_MAX_STR_LENGTH)) { >>> + core->mode = XSDIRXSS_SDI_STD_6G; >>> + } else if (!strncmp(sdi_std, "3G_SDI", XSDIRX_MAX_STR_LENGTH)) { >>> + core->mode = XSDIRXSS_SDI_STD_3G; >>> + } else { >>> + dev_err(dev, "Invalid Line Rate\n"); >>> + return -EINVAL; >>> + } >>> + dev_dbg(dev, "SDI Rx Line Rate = %s, mode = %d\n", sdi_std, >>> + core->mode); >>> + >>> + ret = of_property_read_u32(node, "xlnx,bpp", &core->bpc); >>> + if (ret < 0) { >>> + dev_err(dev, "failed to get xlnx,bpp\n"); >>> + return ret; >>> + } >>> + >>> + if (core->bpc != 10 && core->bpc != 12) { >>> + dev_err(dev, "bits per component=%u. Can be 10 or 12 only\n", >>> + core->bpc); >>> + return -EINVAL; >>> + } >>> + >>> + ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, >>> + >> FWNODE_GRAPH_ENDPOINT_NEXT); >>> + if (!ep) { >>> + dev_err(dev, "no source port found"); >>> + ret = -EINVAL; >>> + goto dt_parse_done; >>> + } >>> + >>> + rep = fwnode_graph_get_remote_endpoint(ep); >>> + if (!rep) { >>> + dev_err(dev, "no remote sink endpoint found"); >>> + ret = -EINVAL; >>> + } >>> + >>> + fwnode_handle_put(rep); >>> +dt_parse_done: >>> + fwnode_handle_put(ep); >>> + return ret; >>> +} >>> + >>> +static int xsdirxss_probe(struct platform_device *pdev) >>> +{ >>> + struct v4l2_subdev *subdev; >>> + struct xsdirxss_state *xsdirxss; >>> + struct xsdirxss_core *core; >>> + struct device *dev; >>> + int ret; >>> + unsigned int num_ctrls, num_edh_ctrls = 0, i; >>> + >>> + xsdirxss = devm_kzalloc(&pdev->dev, sizeof(*xsdirxss), GFP_KERNEL); >>> + if (!xsdirxss) >>> + return -ENOMEM; >>> + >>> + xsdirxss->core.dev = &pdev->dev; >>> + core = &xsdirxss->core; >>> + dev = core->dev; >>> + >>> + /* Register interrupt handler */ >>> + core->irq = platform_get_irq(pdev, 0); >>> + ret = devm_request_threaded_irq(dev, core->irq, NULL, >>> + xsdirxss_irq_handler, IRQF_ONESHOT, >>> + dev_name(dev), xsdirxss); >>> + if (ret) { >>> + dev_err(dev, "Err = %d Interrupt handler reg failed!\n", >>> + ret); >>> + return ret; >>> + } >>> + >>> + core->num_clks = ARRAY_SIZE(xsdirxss_clks); >>> + core->clks = devm_kcalloc(dev, core->num_clks, >>> + sizeof(*core->clks), GFP_KERNEL); >>> + if (!core->clks) >>> + return -ENOMEM; >>> + >>> + for (i = 0; i < core->num_clks; i++) >>> + core->clks[i].id = xsdirxss_clks[i]; >>> + >>> + ret = devm_clk_bulk_get(dev, core->num_clks, core->clks); >>> + if (ret) >>> + return ret; >>> + >>> + ret = clk_bulk_prepare_enable(core->num_clks, core->clks); >>> + if (ret) >>> + return ret; >>> + >>> + ret = xsdirxss_parse_of(xsdirxss); >>> + if (ret < 0) >>> + goto clk_err; >>> + >>> + core->iomem = devm_platform_ioremap_resource(pdev, 0); >>> + if (IS_ERR(core->iomem)) { >>> + ret = PTR_ERR(core->iomem); >>> + goto clk_err; >>> + } >>> + >>> + /* Reset the core */ >>> + xsdirx_streamflow_control(core, false); >>> + xsdirx_core_disable(core); >>> + xsdirx_clearintr(core, XSDIRX_INTR_ALL_MASK); >>> + xsdirx_disableintr(core, XSDIRX_INTR_ALL_MASK); >>> + xsdirx_enableintr(core, XSDIRX_INTR_ALL_MASK); >>> + xsdirx_globalintr(core, true); >>> + xsdirxss_write(core, XSDIRX_CRC_ERRCNT_REG, 0xFFFF); >>> + >>> + /* Initialize V4L2 subdevice and media entity */ >>> + xsdirxss->pad.flags = MEDIA_PAD_FL_SOURCE; >>> + >>> + /* Initialize the default format */ >>> + if (core->bpc == 10) >>> + xsdirxss->default_format.code = >> MEDIA_BUS_FMT_UYVY10_1X20; >>> + else >>> + xsdirxss->default_format.code = >> MEDIA_BUS_FMT_UYVY12_1X24; >>> + xsdirxss->default_format.field = V4L2_FIELD_NONE; >>> + xsdirxss->default_format.colorspace = V4L2_COLORSPACE_DEFAULT; >> >> This shouldn't be DEFAULT. Can you explain a bit how colorspace (or >> colorimetry >> in general) is determined for SDI? >> > > That is correct. As mentioned earlier the colorspace in SDI is determined by bit 5 and 4 of byte 3 > in the 4 byte ST 352 payload as per SMPTE 2081-10:2018 > > b5:b4 = 0h identifies Rec 709 colorimetry in accordance with Recommendation ITU-R BT.709 as referenced by SMPTE ST 274 > b5:b4 = 1h identifies that the colorimetry is defined in the Color VANC packet as defined in SMPTE ST 2048-1 > b5:b4 = 2h identifies UHDTV colorimetry in accordance with the reference primaries and reference white as defined in SMPTE ST 2036-1. See Note 2 to Table 3. > b5:b4 = 3h identifies unknown colorimetry OK. Based on that I'd pick REC709 as the default colorspace. This will be updated to the actual colorspace when you receive a new video stream and can extract this information. > >>> + xsdirxss->default_format.width = XSDIRX_DEFAULT_WIDTH; >>> + xsdirxss->default_format.height = XSDIRX_DEFAULT_HEIGHT; >>> + >>> + xsdirxss->format = xsdirxss->default_format; >>> + >>> + /* Initialize V4L2 subdevice and media entity */ >>> + subdev = &xsdirxss->subdev; >>> + v4l2_subdev_init(subdev, &xsdirxss_ops); >>> + >>> + subdev->dev = &pdev->dev; >>> + strscpy(subdev->name, dev_name(dev), sizeof(subdev->name)); >>> + >>> + subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | >> V4L2_SUBDEV_FL_HAS_DEVNODE; >>> + >>> + subdev->entity.ops = &xsdirxss_media_ops; >>> + >>> + v4l2_set_subdevdata(subdev, xsdirxss); >>> + >>> + ret = media_entity_pads_init(&subdev->entity, 1, &xsdirxss->pad); >>> + if (ret < 0) >>> + goto error; >>> + >>> + /* Initialise and register the controls */ >>> + num_ctrls = ARRAY_SIZE(xsdirxss_ctrls); >>> + >>> + if (core->include_edh) >>> + num_edh_ctrls = ARRAY_SIZE(xsdirxss_edh_ctrls); >>> + >>> + v4l2_ctrl_handler_init(&xsdirxss->ctrl_handler, >>> + (num_ctrls + num_edh_ctrls)); >>> + >>> + for (i = 0; i < num_ctrls; i++) { >>> + struct v4l2_ctrl *ctrl; >>> + >>> + dev_dbg(dev, "%d %s ctrl = 0x%x\n", i, xsdirxss_ctrls[i].name, >>> + xsdirxss_ctrls[i].id); >>> + >>> + ctrl = v4l2_ctrl_new_custom(&xsdirxss->ctrl_handler, >>> + &xsdirxss_ctrls[i], NULL); >>> + if (!ctrl) { >>> + dev_dbg(dev, "Failed to add %s ctrl\n", >>> + xsdirxss_ctrls[i].name); >>> + goto error; >>> + } >>> + } >>> + >>> + if (core->include_edh) { >>> + for (i = 0; i < num_edh_ctrls; i++) { >>> + struct v4l2_ctrl *ctrl; >>> + >>> + dev_dbg(dev, "%d %s ctrl = 0x%x\n", i, >>> + xsdirxss_edh_ctrls[i].name, >>> + xsdirxss_edh_ctrls[i].id); >>> + >>> + ctrl = v4l2_ctrl_new_custom(&xsdirxss->ctrl_handler, >>> + &xsdirxss_edh_ctrls[i], >>> + NULL); >>> + if (!ctrl) { >>> + dev_dbg(dev, "Failed to add %s ctrl\n", >>> + xsdirxss_edh_ctrls[i].name); >>> + goto error; >>> + } >>> + } >>> + } >>> + >>> + if (xsdirxss->ctrl_handler.error) { >>> + dev_err(dev, "failed to add controls\n"); >>> + ret = xsdirxss->ctrl_handler.error; >>> + goto error; >>> + } >>> + >>> + subdev->ctrl_handler = &xsdirxss->ctrl_handler; >>> + >>> + ret = v4l2_ctrl_handler_setup(&xsdirxss->ctrl_handler); >>> + if (ret < 0) { >>> + dev_err(dev, "failed to set controls\n"); >>> + goto error; >>> + } >>> + >>> + platform_set_drvdata(pdev, xsdirxss); >>> + >>> + ret = v4l2_async_register_subdev(subdev); >>> + if (ret < 0) { >>> + dev_err(dev, "failed to register subdev\n"); >>> + goto error; >>> + } >>> + >>> + xsdirxss->streaming = false; >>> + >>> + xsdirx_core_enable(core); >>> + >>> + dev_info(dev, "probe success\n"); >>> + >>> + return 0; >>> +error: >>> + v4l2_ctrl_handler_free(&xsdirxss->ctrl_handler); >>> + media_entity_cleanup(&subdev->entity); >>> + xsdirx_globalintr(core, false); >>> + xsdirx_disableintr(core, XSDIRX_INTR_ALL_MASK); >>> +clk_err: >>> + clk_bulk_disable_unprepare(core->num_clks, core->clks); >>> + return ret; >>> +} >>> + >>> +static int xsdirxss_remove(struct platform_device *pdev) >>> +{ >>> + struct xsdirxss_state *xsdirxss = platform_get_drvdata(pdev); >>> + struct xsdirxss_core *core = &xsdirxss->core; >>> + struct v4l2_subdev *subdev = &xsdirxss->subdev; >>> + >>> + v4l2_async_unregister_subdev(subdev); >>> + v4l2_ctrl_handler_free(&xsdirxss->ctrl_handler); >>> + media_entity_cleanup(&subdev->entity); >>> + >>> + xsdirx_globalintr(core, false); >>> + xsdirx_disableintr(core, XSDIRX_INTR_ALL_MASK); >>> + xsdirx_core_disable(core); >>> + xsdirx_streamflow_control(core, false); >>> + >>> + clk_bulk_disable_unprepare(core->num_clks, core->clks); >>> + >>> + return 0; >>> +} >>> + >>> +static const struct of_device_id xsdirxss_of_id_table[] = { >>> + { .compatible = "xlnx,v-smpte-uhdsdi-rx-ss-2.0" }, >>> + { } >>> +}; >>> +MODULE_DEVICE_TABLE(of, xsdirxss_of_id_table); >>> + >>> +static struct platform_driver xsdirxss_driver = { >>> + .driver = { >>> + .name = "xilinx-sdirxss", >>> + .of_match_table = xsdirxss_of_id_table, >>> + }, >>> + .probe = xsdirxss_probe, >>> + .remove = xsdirxss_remove, >>> +}; >>> + >>> +module_platform_driver(xsdirxss_driver); >>> + >>> +MODULE_AUTHOR("Vishal Sagar "); >>> +MODULE_DESCRIPTION("Xilinx SDI Rx Subsystem Driver"); >>> +MODULE_LICENSE("GPL v2"); >>> diff --git a/include/uapi/linux/xilinx-sdirxss.h b/include/uapi/linux/xilinx- >> sdirxss.h >>> new file mode 100644 >>> index 000000000000..6f2a093968d9 >>> --- /dev/null >>> +++ b/include/uapi/linux/xilinx-sdirxss.h >>> @@ -0,0 +1,179 @@ >>> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ >>> +/* >>> + * Xilinx SDI Rx Subsystem mode, event, custom timings >>> + * and flag definitions. >>> + * >>> + * Copyright (C) 2019 - 2020 Xilinx, Inc. >>> + * >>> + * Contacts: Vishal Sagar >>> + */ >>> + >>> +#ifndef __UAPI_XILINX_SDIRXSS_H__ >>> +#define __UAPI_XILINX_SDIRXSS_H__ >>> + >>> +#include >>> +#include >>> +#include >>> + >>> +/* >>> + * Events >>> + * >>> + * V4L2_EVENT_XILINX_SDIRX_UNDERFLOW: Video in to AXI4 Stream core >> underflowed >>> + * V4L2_EVENT_XILINX_SDIRX_OVERFLOW: Video in to AXI4 Stream core >> overflowed >>> + */ >>> +#define V4L2_EVENT_XILINX_SDIRX_CLASS >> (V4L2_EVENT_PRIVATE_START | 0x200) >>> +#define V4L2_EVENT_XILINX_SDIRX_UNDERFLOW >> (V4L2_EVENT_XILINX_SDIRX_CLASS | 0x1) >>> +#define V4L2_EVENT_XILINX_SDIRX_OVERFLOW >> (V4L2_EVENT_XILINX_SDIRX_CLASS | 0x2) >>> + >>> +/* >>> + * This enum is used to prepare the bitmask of modes to be detected >>> + */ >>> +enum { >>> + XSDIRX_MODE_SD_OFFSET = 0, >>> + XSDIRX_MODE_HD_OFFSET, >>> + XSDIRX_MODE_3G_OFFSET, >>> + XSDIRX_MODE_6G_OFFSET, >>> + XSDIRX_MODE_12GI_OFFSET, >>> + XSDIRX_MODE_12GF_OFFSET, >>> + XSDIRX_MODE_NUM_SUPPORTED, >>> +}; >>> + >>> +#define XSDIRX_DETECT_ALL_MODES >> (BIT(XSDIRX_MODE_SD_OFFSET) | \ >>> + BIT(XSDIRX_MODE_HD_OFFSET) | \ >>> + BIT(XSDIRX_MODE_3G_OFFSET) | \ >>> + BIT(XSDIRX_MODE_6G_OFFSET) | \ >>> + BIT(XSDIRX_MODE_12GI_OFFSET) | \ >>> + BIT(XSDIRX_MODE_12GF_OFFSET)) >>> + >>> +/* >>> + * EDH Error Types >>> + * ANC - Ancillary Data Packet Errors >>> + * FF - Full Field Errors >>> + * AP - Active Portion Errors >>> + */ >>> + >>> +#define XSDIRX_EDH_ERRCNT_ANC_EDH_ERR BIT(0) >>> +#define XSDIRX_EDH_ERRCNT_ANC_EDA_ERR BIT(1) >>> +#define XSDIRX_EDH_ERRCNT_ANC_IDH_ERR BIT(2) >>> +#define XSDIRX_EDH_ERRCNT_ANC_IDA_ERR BIT(3) >>> +#define XSDIRX_EDH_ERRCNT_ANC_UES_ERR BIT(4) >>> +#define XSDIRX_EDH_ERRCNT_FF_EDH_ERR BIT(5) >>> +#define XSDIRX_EDH_ERRCNT_FF_EDA_ERR BIT(6) >>> +#define XSDIRX_EDH_ERRCNT_FF_IDH_ERR BIT(7) >>> +#define XSDIRX_EDH_ERRCNT_FF_IDA_ERR BIT(8) >>> +#define XSDIRX_EDH_ERRCNT_FF_UES_ERR BIT(9) >>> +#define XSDIRX_EDH_ERRCNT_AP_EDH_ERR BIT(10) >>> +#define XSDIRX_EDH_ERRCNT_AP_EDA_ERR BIT(11) >>> +#define XSDIRX_EDH_ERRCNT_AP_IDH_ERR BIT(12) >>> +#define XSDIRX_EDH_ERRCNT_AP_IDA_ERR BIT(13) >>> +#define XSDIRX_EDH_ERRCNT_AP_UES_ERR BIT(14) >>> +#define XSDIRX_EDH_ERRCNT_PKT_CHKSUM_ERR BIT(15) >>> + >>> +#define XSDIRX_EDH_ALLERR_MASK 0xFFFF >>> + >>> +/* Xilinx DV timings not in mainline yet */ >>> +#define XLNX_V4L2_DV_BT_2048X1080P24 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 74250000, 510, 44, 148, 4, 5, 36, 0, 0, 0, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_2048X1080P25 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 74250000, 400, 44, 148, 4, 5, 36, 0, 0, 0, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_2048X1080P30 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 74250000, 66, 20, 66, 4, 5, 36, 0, 0, 0, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_2048X1080I48 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(2048, 1080, 1, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 74250000, 329, 44, 329, 2, 5, 15, 3, 5, 15, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_2048X1080I50 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(2048, 1080, 1, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 74250000, 274, 44, 274, 2, 5, 15, 3, 5, 15, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_2048X1080I60 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(2048, 1080, 1, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 74250000, 66, 20, 66, 2, 5, 15, 3, 5, 15, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_1920X1080P48 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 148500000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_2048X1080P48 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 148500000, 510, 44, 148, 4, 5, 36, 0, 0, 0, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_2048X1080P50 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 148500000, 400, 44, 148, 4, 5, 36, 0, 0, 0, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_2048X1080P60 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 148500000, 88, 44, 20, 4, 5, 36, 0, 0, 0, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_3840X2160P48 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 594000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_4096X2160P48 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 594000000, 1020, 88, 296, 8, 10, 72, 0, 0, 0, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >>> + >>> +#define XLNX_V4L2_DV_BT_1920X1080I48 { \ >>> + .type = V4L2_DV_BT_656_1120, \ >>> + V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \ >>> + V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ >>> + 148500000, 371, 88, 371, 2, 5, 15, 3, 5, 15, \ >>> + V4L2_DV_BT_STD_SDI) \ >>> +} >> >> Why not add these to v4l2-dv-timings.h? I do need to know on which standard >> they are based. >> > > Currently these are based off a timing table used in the corresponding bare metal driver. > I will try to get the standards from which these are based on. > Meanwhile I hope it is ok to add them as custom timings. For now, but this really needs to be sorted. The 2048x1080 timings appear to be DCI Digital Cinema related. 3840x2160p48 is a CTA-861 timing (VIC 114) and 4096x2160p48 is VIC 115. I'm not sure where the 1920x1080i48 timings come from. The two CTA-derived timings can definitely be added to v4l2-dv-timings.h. > >>> + >>> +#endif /* __UAPI_XILINX_SDIRXSS_H__ */ >>> diff --git a/include/uapi/linux/xilinx-v4l2-controls.h >> b/include/uapi/linux/xilinx-v4l2-controls.h >>> index b6441fe705c5..e9de65e82642 100644 >>> --- a/include/uapi/linux/xilinx-v4l2-controls.h >>> +++ b/include/uapi/linux/xilinx-v4l2-controls.h >> >> Why is this in a separate header? It seems to me that it makes more sense to >> have >> a single public header for this driver. >> > > I think the xilinx-v4l2-controls.h is created to house all custom controls of Xilinx V4L2 drivers. > Since the Xilinx Video Test Pattern generator has its controls in the xilinx-v4l2-controls.h, > I decided to keep the controls in this file and the events in the SDI Rx specific header. So the TPG controls are shared between different xilinx IP blocks? Assuming that the controls you add here for your driver are specific to just this IP block, I would add them to xilinx-sdirxss.h instead. Looking at xilinx-v4l2-controls.h: it shouldn't set V4L2_CID_XILINX_OFFSET/BASE here, instead it should reserve the range in v4l2-controls.h. This to ensure CIDs reserved here do not clash with other CIDs reserved by other drivers. For the controls specific to this driver I would also reserve your own range in v4l2-controls.h, rather than taking it from the range reserved by xilinx-v4l2-controls.h. Regards, Hans > >>> @@ -71,4 +71,71 @@ >>> /* Noise level */ >>> #define V4L2_CID_XILINX_TPG_NOISE_GAIN >> (V4L2_CID_XILINX_TPG + 17) >>> >>> +/* >>> + * Xilinx SDI Rx Subsystem >>> + */ >>> + >>> +/* The base for the sdi rx driver controls. >>> + * We reserve 32 controls for this driver. >>> + * >>> + * The V4L2_CID_XILINX_SDIRX_EDH_* controls are present only if >>> + * EDH is enabled. >>> + * The controls which can be set should only be set before enabling >>> + * streaming. The controls which can be got should be called while >>> + * streaming to get correct values. >>> + * The V4L2_CID_XILINX_SDIRX_MODE_DETECT can be called when query >> dv timing >>> + * returns a valid timing. >>> + */ >>> + >>> +#define V4L2_CID_XILINX_SDIRX >> (V4L2_CID_XILINX_BASE + 0x20) >>> + >>> +/* Framer Control to enable or disable the framer */ >>> +#define V4L2_CID_XILINX_SDIRX_FRAMER >> (V4L2_CID_XILINX_SDIRX + 1) >>> +/* >>> + * Video Lock Window Control to set the video lock window value >>> + * This is the amount of time the mode and transport stream need >>> + * to be locked before a video lock interrupt occurs. >>> + */ >>> +#define V4L2_CID_XILINX_SDIRX_VIDLOCK_WINDOW >> (V4L2_CID_XILINX_SDIRX + 2) >>> +/* EDH Error Mask Control to enable EDH error count */ >>> +#define V4L2_CID_XILINX_SDIRX_EDH_ERRCNT_ENABLE >> (V4L2_CID_XILINX_SDIRX + 3) >>> +/* >>> + * Mode search Control to pass the bit mask of modes to detect. >>> + * >>> + * bit 0 set to detect SD mode, >>> + * bit 1 set to detect HD mode, >>> + * bit 2 set to detect 3G (3GA & 3GB) mode, >>> + * bit 3 set to detect 6G mode, >>> + * bit 4 set to detect 12G integer frame rate mode, >>> + * bit 5 set to detect 12G fractional frame rate mode, >>> + */ >>> +#define V4L2_CID_XILINX_SDIRX_SEARCH_MODES >> (V4L2_CID_XILINX_SDIRX + 4) >>> +/* >>> + * Get Detected Mode control >>> + * >>> + * Control Value - Mode detected >>> + * 0 - SD >>> + * 1 - HD >>> + * 2 - 3G (3GA & 3GB) >>> + * 3 - 6G >>> + * 4 - 12G integer frame rate >>> + * 5 - 12G fractional frame rate >>> + */ >>> +#define V4L2_CID_XILINX_SDIRX_MODE_DETECT >> (V4L2_CID_XILINX_SDIRX + 5) >>> +/* Get number of CRC errors status control */ >>> +#define V4L2_CID_XILINX_SDIRX_CRC >> (V4L2_CID_XILINX_SDIRX + 6) >>> +/* Get EDH error count control */ >>> +#define V4L2_CID_XILINX_SDIRX_EDH_ERRCNT >> (V4L2_CID_XILINX_SDIRX + 7) >>> +/* Get EDH status control */ >>> +#define V4L2_CID_XILINX_SDIRX_EDH_STATUS >> (V4L2_CID_XILINX_SDIRX + 8) >>> +/* Get Transport Interlaced status whether it is interlaced or not */ >>> +#define V4L2_CID_XILINX_SDIRX_TS_IS_INTERLACED >> (V4L2_CID_XILINX_SDIRX + 9) >>> +/* Get number of Active Streams */ >>> +#define V4L2_CID_XILINX_SDIRX_ACTIVE_STREAMS >> (V4L2_CID_XILINX_SDIRX + 10) >>> +/* >>> + * Get if the detected mode is 3GB. >>> + * Can be used to distinguished between 3GA and 3GB >>> + */ >>> +#define V4L2_CID_XILINX_SDIRX_IS_3GB >> (V4L2_CID_XILINX_SDIRX + 11) >>> + >>> #endif /* __UAPI_XILINX_V4L2_CONTROLS_H__ */ >>> >> >> Regards, >> >> Hans > > Regards > Vishal Sagar > 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 X-Spam-Level: X-Spam-Status: No, score=-8.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AF320C433E0 for ; Tue, 9 Jun 2020 15:03:08 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 4EF8B20774 for ; Tue, 9 Jun 2020 15:03:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="JrPZK9ms"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=xs4all.nl header.i=@xs4all.nl header.b="Mx2FYbRZ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4EF8B20774 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=xs4all.nl Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date: Message-ID:From:References:To:Subject:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=9TV16VQfjnm1E38y89sz6EucrbNEgZT1kltuqtNvA28=; b=JrPZK9msAgFa7lBfI8DHZYwPZ+ U4tF9gTQz9jGAketePJZMUoKM1XoMqAz/vG8k8QShlnock3VNSVemT9IFC3WELeOmyvG7NYNRmVr4 Mnqhaawu+eiRBoKtmNUWLR4M+IbUEzQk60I1d32ltkMIco5SP80NSWwbb5YJEdc/YyUeYGhOPjIPn bRSL8Xi5qjLmU1mx4rkmdc5yyiRsjv7cBsIrhZ4G03G5pT4XBxD319jEAmBZ4tagGCNWHRav5Wi3a BTHdp5ld6+H/PiOJKo+7XenyfnFy2+fEsJ8UOUP4euJGWRPnGzu9pSHutd8MFHBGAVxR22K2xPF+Q VKPFt/NQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jifm9-00029c-S8; Tue, 09 Jun 2020 15:02:53 +0000 Received: from lb3-smtp-cloud7.xs4all.net ([194.109.24.31]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jifl8-0001zD-2u for linux-arm-kernel@lists.infradead.org; Tue, 09 Jun 2020 15:01:54 +0000 Received: from cust-b5b5937f ([IPv6:fc0c:c16d:66b8:757f:c639:739b:9d66:799d]) by smtp-cloud7.xs4all.net with ESMTPA id ifkujUBrRNp2zifkyjlyoh; Tue, 09 Jun 2020 17:01:46 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xs4all.nl; s=s1; t=1591714906; bh=2UBNyGiGQ39Gr5fhoeQ/g57it7qDzgt8h68l+Yh7uSo=; h=Subject:To:From:Message-ID:Date:MIME-Version:Content-Type:From: Subject; b=Mx2FYbRZ9Yk0KQkpbkJXXOr/ejLeJgWwYxEZVMLNU2ZVBbowF1vsVBJhBrxQv4h7c 9zxWCkXN0jm8oZyBP4rpUK2hsQLou8QEyC7hIU/j96EtewPOGsop5pcL5WVTwDIVsi asdd0YDwWrygf8syA8IFp92IRa70/6QrUZTGdfuKXijUKGlsSEVaFXR1qOZjgyZbsZ vB8Yh/RkUm7bJ3cG/0zPEicb8A0W3xBnHZK/H4e3qfZC/VnzFoFavz12UDW0ZKB48o n8ftC6RKwv6mENii0BFISk1cylWH178VJ8PLDTxBaVodt5Mph97X82HcL6411qWz7s lkFMxvy/UBnnA== Subject: Re: [PATCH v2 2/2] media: v4l: xilinx: Add Xilinx UHD-SDI Rx Subsystem driver To: Vishal Sagar , Hyun Kwon , "laurent.pinchart@ideasonboard.com" , "mchehab@kernel.org" , "robh+dt@kernel.org" , "mark.rutland@arm.com" , Michal Simek , "linux-media@vger.kernel.org" , "devicetree@vger.kernel.org" , "hans.verkuil@cisco.com" , "linux-arm-kernel@lists.infradead.org" , "linux-kernel@vger.kernel.org" , Dinesh Kumar , Sandip Kothari , Joe Perches References: <20200429141705.18755-1-vishal.sagar@xilinx.com> <20200429141705.18755-3-vishal.sagar@xilinx.com> <368b7efb-3faf-bb71-2bd0-826f2ab031e6@xs4all.nl> From: Hans Verkuil Message-ID: <7cecf608-a001-5986-8792-35c312dcc961@xs4all.nl> Date: Tue, 9 Jun 2020 17:01:36 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-CMAE-Envelope: MS4wfHwnUPLBZOiuFRgK7hI0kI2yqt/Chzc6XqbOErlzI+r7NrM+eNruttGZxWbmLQqP6U8jINREpscVwCksOA5A/z06kT/x2FZKm6r0HWqD5LxpJ5iQjnHW CNMz2qh0nEhuR56A+Y9MuGSdVt9Ch9fu9HlmNwX84/QQ5Ro0Di9ZrAq3g04WpHbznJpIl05aPwGve/OLmhlP41f35a+ftxkf93cF6ggH7j2DV9Us0gs1Gnop xqkRL6tCNaCq3F1XAdb3+UMjyGZiRzUSKfWNGIi1mrtzPVlSx94C+hBxCYXHqfu0bn3V+G3XurXEL2ElqGpadQy9UTtiJdJSrhoTSdcyMDDYvECd1J8csdZo 2KmmZE8Uzwhji0IGqzENkUsMNPIhBFXEetVUV2PJGaWT9Vw5K06qTZvRKM+jqNbgk0KDZAajIpo+tracnFfgglqmGA3yew4ip2bmXxmlOWLsq5UDzYUqYnbD XhNsdS97MFGX2hSKK9IrtePr7bR7I2nx4txKpwYUXBF/vJ4VZzuoTd2cveIEjqXHEl2X9T/bn1virLd7Wd6Lt7r/YUt5X0xEUfinirCMjEwOyT/D0J2fEZjX jFcdeBNXc7wjDD1Oz9E200Q04IZ0zn8FKqWxZDKl57H8I1VSKJhcMIlw2ZoNVa0/kko= X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200609_080150_691125_65E3CB49 X-CRM114-Status: GOOD ( 25.30 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org T24gMDEvMDYvMjAyMCAxNjo1OSwgVmlzaGFsIFNhZ2FyIHdyb3RlOgo+IEhpIEhhbnMsCj4gCj4g VGhhbmtzIGZvciByZXZpZXdpbmchCj4gCj4+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tCj4+ IEZyb206IEhhbnMgVmVya3VpbCA8aHZlcmt1aWxAeHM0YWxsLm5sPgo+PiBTZW50OiBXZWRuZXNk YXksIE1heSA2LCAyMDIwIDM6MjUgUE0KPj4gVG86IFZpc2hhbCBTYWdhciA8dnNhZ2FyQHhpbGlu eC5jb20+OyBIeXVuIEt3b24gPGh5dW5rQHhpbGlueC5jb20+Owo+PiBsYXVyZW50LnBpbmNoYXJ0 QGlkZWFzb25ib2FyZC5jb207IG1jaGVoYWJAa2VybmVsLm9yZzsKPj4gcm9iaCtkdEBrZXJuZWwu b3JnOyBtYXJrLnJ1dGxhbmRAYXJtLmNvbTsgTWljaGFsIFNpbWVrCj4+IDxtaWNoYWxzQHhpbGlu eC5jb20+OyBsaW51eC1tZWRpYUB2Z2VyLmtlcm5lbC5vcmc7Cj4+IGRldmljZXRyZWVAdmdlci5r ZXJuZWwub3JnOyBoYW5zLnZlcmt1aWxAY2lzY28uY29tOyBsaW51eC1hcm0tCj4+IGtlcm5lbEBs aXN0cy5pbmZyYWRlYWQub3JnOyBsaW51eC1rZXJuZWxAdmdlci5rZXJuZWwub3JnOyBEaW5lc2gg S3VtYXIKPj4gPGRpbmVzaGtAeGlsaW54LmNvbT47IFNhbmRpcCBLb3RoYXJpIDxzYW5kaXBrQHhp bGlueC5jb20+OyBKb2UgUGVyY2hlcwo+PiA8am9lQHBlcmNoZXMuY29tPgo+PiBTdWJqZWN0OiBS ZTogW1BBVENIIHYyIDIvMl0gbWVkaWE6IHY0bDogeGlsaW54OiBBZGQgWGlsaW54IFVIRC1TREkg UnggU3Vic3lzdGVtCj4+IGRyaXZlcgo+Pgo+PiBIaSBWaXNoYWwsCj4+Cj4+IFRoYW5rIHlvdSBm b3IgdGhpcyBwYXRjaC4KPj4KPj4gSSBoYXZlIHNvbWUgY29tbWVudHMgYmVsb3c6Cj4+Cj4+IE9u IDI5LzA0LzIwMjAgMTY6MTcsIFZpc2hhbCBTYWdhciB3cm90ZToKPj4+IFRoZSBYaWxpbnggVUhE LVNESSBSeCBzdWJzeXN0ZW0gc29mdCBJUCBpcyB1c2VkIHRvIGNhcHR1cmUgbmF0aXZlIFNESQo+ Pj4gc3RyZWFtcyBmcm9tIFNESSBzb3VyY2VzIGxpa2UgU0RJIGJyb2FkY2FzdCBlcXVpcG1lbnQg bGlrZSBjYW1lcmFzIGFuZAo+Pj4gbWl4ZXJzLiBUaGlzIGJsb2NrIG91dHB1dHMgZWl0aGVyIG5h dGl2ZSBTREksIG5hdGl2ZSB2aWRlbyBvcgo+Pj4gQVhJNC1TdHJlYW0gY29tcGxpYW50IGRhdGEg c3RyZWFtIGZvciBmdXJ0aGVyIHByb2Nlc3NpbmcuIFBsZWFzZSByZWZlcgo+Pj4gdG8gUEcyOTAg Zm9yIGRldGFpbHMuCj4+Pgo+Pj4gVGhlIGRyaXZlciBpcyB1c2VkIHRvIGNvbmZpZ3VyZSB0aGUg SVAgdG8gYWRkIGZyYW1lciwgc2VhcmNoIGZvcgo+Pj4gc3BlY2lmaWMgbW9kZXMsIGdldCB0aGUg ZGV0ZWN0ZWQgbW9kZSwgc3RyZWFtIHBhcmFtZXRlcnMsIGVycm9ycywgZXRjLgo+Pj4gSXQgYWxz byBnZW5lcmF0ZXMgZXZlbnRzIGZvciB2aWRlbyBsb2NrL3VubG9jaywgYnJpZGdlIG92ZXIvdW5k ZXIgZmxvdy4KPj4+Cj4+PiBUaGUgZHJpdmVyIHN1cHBvcnRzIDEwLzEyIGJwYyBZVVYgNDIyIG1l ZGlhIGJ1cyBmb3JtYXQgY3VycmVudGx5LiBJdCBhbHNvCj4+PiBkZWNvZGVzIHRoZSBzdHJlYW0g cGFyYW1ldGVycyBiYXNlZCBvbiB0aGUgU1QzNTIgcGFja2V0IGVtYmVkZGVkIGluIHRoZQo+Pj4g c3RyZWFtLiBJbiBjYXNlIHRoZSBTVDM1MiBwYWNrZXQgaXNuJ3QgcHJlc2VudCBpbiB0aGUgc3Ry ZWFtLCB0aGUgY29yZSdzCj4+PiBkZXRlY3RlZCBwcm9wZXJ0aWVzIGFyZSB1c2VkIHRvIHNldCBz dHJlYW0gcHJvcGVydGllcy4KPj4+Cj4+PiBUaGUgZHJpdmVyIGN1cnJlbnRseSBzdXBwb3J0cyBv bmx5IHRoZSBBWEk0LVN0cmVhbSBJUCBjb25maWd1cmF0aW9uLgo+Pj4KPj4+IFNpZ25lZC1vZmYt Ynk6IFZpc2hhbCBTYWdhciA8dmlzaGFsLnNhZ2FyQHhpbGlueC5jb20+Cj4+PiAtLS0KCjxzbmlw PgoKPj4+ICsvKioKPj4+ICsgKiB4c2Rpcnhzc19zZXRfZm9ybWF0IC0gVGhpcyBpcyB1c2VkIHRv IHNldCB0aGUgcGFkIGZvcm1hdAo+Pj4gKyAqIEBzZDogUG9pbnRlciB0byBWNEwyIFN1YiBkZXZp Y2Ugc3RydWN0dXJlCj4+PiArICogQGNmZzogUG9pbnRlciB0byBzdWIgZGV2aWNlIHBhZCBpbmZv cm1hdGlvbiBzdHJ1Y3R1cmUKPj4+ICsgKiBAZm10OiBQb2ludGVyIHRvIHBhZCBsZXZlbCBtZWRp YSBidXMgZm9ybWF0Cj4+PiArICoKPj4+ICsgKiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgdG8gc2V0 IHRoZSBwYWQgZm9ybWF0Lgo+Pj4gKyAqIFNpbmNlIHRoZSBwYWQgZm9ybWF0IGlzIGZpeGVkIGlu IGhhcmR3YXJlLCBpdCBjYW4ndCBiZQo+Pj4gKyAqIG1vZGlmaWVkIG9uIHJ1biB0aW1lLgo+Pj4g KyAqCj4+PiArICogUmV0dXJuOiAwIG9uIHN1Y2Nlc3MKPj4+ICsgKi8KPj4+ICtzdGF0aWMgaW50 IHhzZGlyeHNzX3NldF9mb3JtYXQoc3RydWN0IHY0bDJfc3ViZGV2ICpzZCwKPj4+ICsJCQkgICAg ICAgc3RydWN0IHY0bDJfc3ViZGV2X3BhZF9jb25maWcgKmNmZywKPj4+ICsJCQkgICAgICAgc3Ry dWN0IHY0bDJfc3ViZGV2X2Zvcm1hdCAqZm10KQo+Pj4gK3sKPj4+ICsJc3RydWN0IHY0bDJfbWJ1 c19mcmFtZWZtdCAqX19mb3JtYXQ7Cj4+PiArCXN0cnVjdCB4c2Rpcnhzc19zdGF0ZSAqeHNkaXJ4 c3MgPSB0b194c2Rpcnhzc3N0YXRlKHNkKTsKPj4+ICsKPj4+ICsJZGV2X2RiZyh4c2Rpcnhzcy0+ Y29yZS5kZXYsCj4+PiArCQkic2V0IHdpZHRoICVkIGhlaWdodCAlZCBjb2RlICVkIGZpZWxkICVk IGNvbG9yc3BhY2UgJWRcbiIsCj4+PiArCQlmbXQtPmZvcm1hdC53aWR0aCwgZm10LT5mb3JtYXQu aGVpZ2h0LAo+Pj4gKwkJZm10LT5mb3JtYXQuY29kZSwgZm10LT5mb3JtYXQuZmllbGQsCj4+PiAr CQlmbXQtPmZvcm1hdC5jb2xvcnNwYWNlKTsKPj4+ICsKPj4+ICsJX19mb3JtYXQgPSBfX3hzZGly eHNzX2dldF9wYWRfZm9ybWF0KHhzZGlyeHNzLCBjZmcsCj4+PiArCQkJCQkgICAgIGZtdC0+cGFk LCBmbXQtPndoaWNoKTsKPj4+ICsKPj4+ICsJLyogQ3VycmVudGx5IHJlc2V0IHRoZSBjb2RlIHRv IG9uZSBmaXhlZCBpbiBoYXJkd2FyZSAqLwo+Pj4gKwkvKiBUT0RPIDogQWRkIGNoZWNrcyBmb3Ig d2lkdGggaGVpZ2h0ICovCj4+PiArCWZtdC0+Zm9ybWF0LmNvZGUgPSBfX2Zvcm1hdC0+Y29kZTsK Pj4KPj4gSXQgc2hvdWxkIGZpbGwgaW4gdGhlIHdpZHRoIGFuZCBoZWlnaHQgYmFzZWQgb24gdGhl IGN1cnJlbnQgRFYgdGltaW5ncy4KPj4gRGl0dG8gZm9yIHRoZSBmaWVsZCAoSSBhc3N1bWUgdGhh dCdzIGZpeGVkIGFzIHdlbGwgYmFzZWQgb24gd2hldGhlciB0aGlzCj4+IGlzIGludGVybGFjZWQg b3Igbm90KS4gSSdtIG5vdCBzdXJlIGhvdyBjb2xvcnNwYWNlIGluZm9ybWF0aW9uIGlzIGhhbmRs ZWQKPj4gZm9yIFNESS4KPj4KPiAKPiBZZXMuIEkgd2lsbCB1cGRhdGUgdGhpcyBsb2dpYyB0byB1 cGRhdGUgdGhlIHdpZHRoLCBoZWlnaHQgYW5kIGZpZWxkIGJhc2VkIG9uIGN1cnJlbnQgRFYgdGlt aW5ncy4KPiBQbGVhc2UgaGF2ZSBhIGxvb2sgYXQgdGhpcyBpbiB0aGUgbmV4dCB2ZXJzaW9uLgo+ IFRoZSBjdXJyZW50IElQIHN1cHBvcnRzIEJUNzA5IGNvbG9yaW1ldHJ5Lgo+IFRoZSBjb2xvcmlt ZXRyeSBpbmZvcm1hdGlvbiBvZiBpbmNvbWluZyBzdHJlYW0gaXMgcHJlc2VudCBpbiB0aGUgU1Qg MzUyIHBheWxvYWQgQnl0ZSAzIChiaXQgNSBhbmQgYml0IDQpIGFzIHBlciBTTVBURSBTVCAyMDgx LTEwOjIwMTguCj4gQjU6NCA9IDAgLT4gQlQgNzA5IGFzIHBlciBTTVBURSBTVCAyNzQgCgpPSywg c28gdGhpcyBjYW4gYmUgZmlsbGVkIGluIGJ5IHRoZSBkcml2ZXIgYXMgd2VsbC4KCj4gCj4+PiAr Cj4+PiArCXJldHVybiAwOwo+Pj4gK30KPj4+ICsKPj4+ICsvKioKPj4+ICsgKiB4c2Rpcnhzc19l bnVtX21idXNfY29kZSAtIEhhbmRsZSBwaXhlbCBmb3JtYXQgZW51bWVyYXRpb24KPj4+ICsgKiBA c2Q6IHBvaW50ZXIgdG8gdjRsMiBzdWJkZXYgc3RydWN0dXJlCj4+PiArICogQGNmZzogVjRMMiBz dWJkZXYgcGFkIGNvbmZpZ3VyYXRpb24KPj4+ICsgKiBAY29kZTogcG9pbnRlciB0byB2NGwyX3N1 YmRldl9tYnVzX2NvZGVfZW51bSBzdHJ1Y3R1cmUKPj4+ICsgKgo+Pj4gKyAqIFJldHVybjogLUVJ TlZBTCBvciB6ZXJvIG9uIHN1Y2Nlc3MKPj4+ICsgKi8KPj4+ICtzdGF0aWMgaW50IHhzZGlyeHNz X2VudW1fbWJ1c19jb2RlKHN0cnVjdCB2NGwyX3N1YmRldiAqc2QsCj4+PiArCQkJCSAgIHN0cnVj dCB2NGwyX3N1YmRldl9wYWRfY29uZmlnICpjZmcsCj4+PiArCQkJCSAgIHN0cnVjdCB2NGwyX3N1 YmRldl9tYnVzX2NvZGVfZW51bQo+PiAqY29kZSkKPj4+ICt7Cj4+PiArCXN0cnVjdCB4c2Rpcnhz c19zdGF0ZSAqeHNkaXJ4c3MgPSB0b194c2Rpcnhzc3N0YXRlKHNkKTsKPj4+ICsJdTMyIGluZGV4 ID0gY29kZS0+aW5kZXg7Cj4+PiArCXUzMiBtYXhpbmRleDsKPj4+ICsKPj4+ICsJaWYgKHhzZGly eHNzLT5jb3JlLmJwYyA9PSAxMCkKPj4+ICsJCW1heGluZGV4ID0gQVJSQVlfU0laRSh4c2Rpcnhz c18xMGJwY19tYnVzX2ZtdHMpOwo+Pj4gKwllbHNlCj4+PiArCQltYXhpbmRleCA9IEFSUkFZX1NJ WkUoeHNkaXJ4c3NfMTJicGNfbWJ1c19mbXRzKTsKPj4+ICsKPj4+ICsJaWYgKGNvZGUtPnBhZCB8 fCBpbmRleCA+PSBtYXhpbmRleCkKPj4+ICsJCXJldHVybiAtRUlOVkFMOwo+Pj4gKwo+Pj4gKwlp ZiAoeHNkaXJ4c3MtPmNvcmUuYnBjID09IDEwKQo+Pj4gKwkJY29kZS0+Y29kZSA9IHhzZGlyeHNz XzEwYnBjX21idXNfZm10c1tpbmRleF07Cj4+PiArCWVsc2UKPj4+ICsJCWNvZGUtPmNvZGUgPSB4 c2Rpcnhzc18xMmJwY19tYnVzX2ZtdHNbaW5kZXhdOwo+Pj4gKwo+Pj4gKwlyZXR1cm4gMDsKPj4+ ICt9Cj4+PiArCj4+PiArLyoqCj4+PiArICogeHNkaXJ4c3NfZW51bV9kdl90aW1pbmdzOiBFbnVt ZXJhdGUgYWxsIHRoZSBzdXBwb3J0ZWQgRFYgdGltaW5ncwo+Pj4gKyAqIEBzZDogcG9pbnRlciB0 byB2NGwyIHN1YmRldiBzdHJ1Y3R1cmUKPj4+ICsgKiBAdGltaW5nczogRFYgdGltaW5ncyBzdHJ1 Y3R1cmUgdG8gYmUgcmV0dXJuZWQuCj4+PiArICoKPj4+ICsgKiBSZXR1cm46IC1FSU5WQUwgaW5j YXNlIG9mIGludmFsaWQgaW5kZXggYW5kIHBhZCBvciB6ZXJvIG9uIHN1Y2Nlc3MKPj4+ICsgKi8K Pj4+ICtzdGF0aWMgaW50IHhzZGlyeHNzX2VudW1fZHZfdGltaW5ncyhzdHJ1Y3QgdjRsMl9zdWJk ZXYgKnNkLAo+Pj4gKwkJCQkgICAgc3RydWN0IHY0bDJfZW51bV9kdl90aW1pbmdzICp0aW1pbmdz KQo+Pj4gK3sKPj4+ICsJaWYgKHRpbWluZ3MtPmluZGV4ID49IEFSUkFZX1NJWkUoZm10X2NhcCkp Cj4+PiArCQlyZXR1cm4gLUVJTlZBTDsKPj4+ICsKPj4+ICsJaWYgKHRpbWluZ3MtPnBhZCAhPSAw KQo+Pj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4+PiArCj4+PiArCXRpbWluZ3MtPnRpbWluZ3MgPSBm bXRfY2FwW3RpbWluZ3MtPmluZGV4XTsKPj4+ICsJcmV0dXJuIDA7Cj4+PiArfQo+Pj4gKwo+Pj4g Ky8qKgo+Pj4gKyAqIHhzZGlyeHNzX3F1ZXJ5X2R2X3RpbWluZ3M6IFF1ZXJ5IGZvciB0aGUgY3Vy cmVudCBEViB0aW1pbmdzCj4+PiArICogQHNkOiBwb2ludGVyIHRvIHY0bDIgc3ViZGV2IHN0cnVj dHVyZQo+Pj4gKyAqIEB0aW1pbmdzOiBEViB0aW1pbmdzIHN0cnVjdHVyZSB0byBiZSByZXR1cm5l ZC4KPj4+ICsgKgo+Pj4gKyAqIFJldHVybjogLUVOT0xDSyB3aGVuIHZpZGVvIGlzIG5vdCBsb2Nr ZWQsIC1FUkFOR0Ugd2hlbiBjb3JyZXNwb25kaW5nCj4+IHRpbWluZwo+Pj4gKyAqIGVudHJ5IGlz IG5vdCBmb3VuZCBvciB6ZXJvIG9uIHN1Y2Nlc3MuCj4+PiArICovCj4+PiArc3RhdGljIGludCB4 c2Rpcnhzc19xdWVyeV9kdl90aW1pbmdzKHN0cnVjdCB2NGwyX3N1YmRldiAqc2QsCj4+PiArCQkJ CSAgICAgc3RydWN0IHY0bDJfZHZfdGltaW5ncyAqdGltaW5ncykKPj4+ICt7Cj4+PiArCXN0cnVj dCB4c2Rpcnhzc19zdGF0ZSAqc3RhdGUgPSB0b194c2Rpcnhzc3N0YXRlKHNkKTsKPj4+ICsJdW5z aWduZWQgaW50IGk7Cj4+PiArCj4+PiArCWlmICghc3RhdGUtPnZpZGxvY2tlZCkKPj4+ICsJCXJl dHVybiAtRU5PTENLOwo+Pj4gKwo+Pj4gKwlmb3IgKGkgPSAwOyBpIDwgQVJSQVlfU0laRSh4c2Rp cnhzc19kdl90aW1pbmdzKTsgaSsrKSB7Cj4+PiArCQlpZiAoc3RhdGUtPmZvcm1hdC53aWR0aCA9 PSB4c2Rpcnhzc19kdl90aW1pbmdzW2ldLndpZHRoICYmCj4+PiArCQkgICAgc3RhdGUtPmZvcm1h dC5oZWlnaHQgPT0geHNkaXJ4c3NfZHZfdGltaW5nc1tpXS5oZWlnaHQgJiYKPj4+ICsJCSAgICBz dGF0ZS0+ZnJhbWVfaW50ZXJ2YWwuZGVub21pbmF0b3IgPT0KPj4+ICsJCSAgICAoeHNkaXJ4c3Nf ZHZfdGltaW5nc1tpXS5mcHMgKiAxMDAwKSkgewo+Pj4gKwkJCSp0aW1pbmdzID0geHNkaXJ4c3Nf ZHZfdGltaW5nc1tpXS5mb3JtYXQ7Cj4+PiArCQkJcmV0dXJuIDA7Cj4+PiArCQl9Cj4+PiArCX0K Pj4+ICsKPj4+ICsJcmV0dXJuIC1FUkFOR0U7Cj4+PiArfQo+Pj4gKwo+Pj4gKy8qIC0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tCj4+PiArICogTWVkaWEgT3BlcmF0aW9ucwo+Pj4gKyAqLwo+Pj4gKwo+Pj4g K3N0YXRpYyBjb25zdCBzdHJ1Y3QgbWVkaWFfZW50aXR5X29wZXJhdGlvbnMgeHNkaXJ4c3NfbWVk aWFfb3BzID0gewo+Pj4gKwkubGlua192YWxpZGF0ZSA9IHY0bDJfc3ViZGV2X2xpbmtfdmFsaWRh dGUKPj4+ICt9Owo+Pj4gKwo+Pj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRsMl9jdHJsX29wcyB4 c2Rpcnhzc19jdHJsX29wcyA9IHsKPj4+ICsJLmdfdm9sYXRpbGVfY3RybCA9IHhzZGlyeHNzX2df dm9sYXRpbGVfY3RybCwKPj4+ICsJLnNfY3RybAk9IHhzZGlyeHNzX3NfY3RybAo+Pj4gK307Cj4+ PiArCj4+PiArc3RhdGljIGNvbnN0IHN0cnVjdCB2NGwyX2N0cmxfY29uZmlnIHhzZGlyeHNzX2Vk aF9jdHJsc1tdID0gewo+Pj4gKwl7Cj4+PiArCQkub3BzCT0gJnhzZGlyeHNzX2N0cmxfb3BzLAo+ Pj4gKwkJLmlkCT0gVjRMMl9DSURfWElMSU5YX1NESVJYX0VESF9FUlJDTlRfRU5BQkxFLAo+Pj4g KwkJLm5hbWUJPSAiU0RJIFJ4IDogRURIIEVycm9yIENvdW50IEVuYWJsZSIsCj4+PiArCQkudHlw ZQk9IFY0TDJfQ1RSTF9UWVBFX0JJVE1BU0ssCj4+PiArCQkubWluCT0gMCwKPj4+ICsJCS5tYXgJ PSBYU0RJUlhfRURIX0FMTEVSUl9NQVNLLAo+Pj4gKwkJLmRlZgk9IDAsCj4+PiArCX0sIHsKPj4+ ICsJCS5vcHMJPSAmeHNkaXJ4c3NfY3RybF9vcHMsCj4+PiArCQkuaWQJPSBWNEwyX0NJRF9YSUxJ TlhfU0RJUlhfRURIX0VSUkNOVCwKPj4+ICsJCS5uYW1lCT0gIlNESSBSeCA6IEVESCBFcnJvciBD b3VudCIsCj4+PiArCQkudHlwZQk9IFY0TDJfQ1RSTF9UWVBFX0lOVEVHRVIsCj4+PiArCQkubWlu CT0gMCwKPj4+ICsJCS5tYXgJPSAweEZGRkYsCj4+PiArCQkuc3RlcAk9IDEsCj4+PiArCQkuZGVm CT0gMCwKPj4+ICsJCS5mbGFncyAgPSBWNEwyX0NUUkxfRkxBR19WT0xBVElMRSB8Cj4+IFY0TDJf Q1RSTF9GTEFHX1JFQURfT05MWSwKPj4+ICsJfSwgewo+Pj4gKwkJLm9wcwk9ICZ4c2Rpcnhzc19j dHJsX29wcywKPj4+ICsJCS5pZAk9IFY0TDJfQ0lEX1hJTElOWF9TRElSWF9FREhfU1RBVFVTLAo+ Pj4gKwkJLm5hbWUJPSAiU0RJIFJ4IDogRURIIFN0YXR1cyIsCj4+PiArCQkudHlwZQk9IFY0TDJf Q1RSTF9UWVBFX0lOVEVHRVIsCj4+PiArCQkubWluCT0gMCwKPj4+ICsJCS5tYXgJPSAweEZGRkZG RkZGLAo+Pj4gKwkJLnN0ZXAJPSAxLAo+Pj4gKwkJLmRlZgk9IDAsCj4+PiArCQkuZmxhZ3MgID0g VjRMMl9DVFJMX0ZMQUdfVk9MQVRJTEUgfAo+PiBWNEwyX0NUUkxfRkxBR19SRUFEX09OTFksCj4+ PiArCX0KPj4+ICt9Owo+Pj4gKwo+Pj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRsMl9jdHJsX2Nv bmZpZyB4c2Rpcnhzc19jdHJsc1tdID0gewo+Pj4gKwl7Cj4+PiArCQkub3BzCT0gJnhzZGlyeHNz X2N0cmxfb3BzLAo+Pj4gKwkJLmlkCT0gVjRMMl9DSURfWElMSU5YX1NESVJYX0ZSQU1FUiwKPj4+ ICsJCS5uYW1lCT0gIlNESSBSeCA6IEVuYWJsZSBGcmFtZXIiLAo+Pj4gKwkJLnR5cGUJPSBWNEwy X0NUUkxfVFlQRV9CT09MRUFOLAo+Pj4gKwkJLm1pbgk9IGZhbHNlLAo+Pj4gKwkJLm1heAk9IHRy dWUsCj4+PiArCQkuc3RlcAk9IDEsCj4+PiArCQkuZGVmCT0gdHJ1ZSwKPj4+ICsJfSwgewo+Pj4g KwkJLm9wcwk9ICZ4c2Rpcnhzc19jdHJsX29wcywKPj4+ICsJCS5pZAk9IFY0TDJfQ0lEX1hJTElO WF9TRElSWF9WSURMT0NLX1dJTkRPVywKPj4+ICsJCS5uYW1lCT0gIlNESSBSeCA6IFZpZGVvIExv Y2sgV2luZG93IiwKPj4+ICsJCS50eXBlCT0gVjRMMl9DVFJMX1RZUEVfSU5URUdFUiwKPj4+ICsJ CS5taW4JPSAwLAo+Pj4gKwkJLm1heAk9IDB4RkZGRkZGRkYsCj4+PiArCQkuc3RlcAk9IDEsCj4+ PiArCQkuZGVmCT0gWFNESVJYX0RFRkFVTFRfVklERU9fTE9DS19XSU5ET1csCj4+PiArCX0sIHsK Pj4+ICsJCS5vcHMJPSAmeHNkaXJ4c3NfY3RybF9vcHMsCj4+PiArCQkuaWQJPSBWNEwyX0NJRF9Y SUxJTlhfU0RJUlhfU0VBUkNIX01PREVTLAo+Pj4gKwkJLm5hbWUJPSAiU0RJIFJ4IDogTW9kZXMg c2VhcmNoIE1hc2siLAo+Pj4gKwkJLnR5cGUJPSBWNEwyX0NUUkxfVFlQRV9CSVRNQVNLLAo+Pj4g KwkJLm1pbgk9IDAsCj4+PiArCQkubWF4CT0gWFNESVJYX0RFVEVDVF9BTExfTU9ERVMsCj4+PiAr CQkuZGVmCT0gWFNESVJYX0RFVEVDVF9BTExfTU9ERVMsCj4+PiArCX0sIHsKPj4+ICsJCS5vcHMJ PSAmeHNkaXJ4c3NfY3RybF9vcHMsCj4+PiArCQkuaWQJPSBWNEwyX0NJRF9YSUxJTlhfU0RJUlhf TU9ERV9ERVRFQ1QsCj4+PiArCQkubmFtZQk9ICJTREkgUnggOiBNb2RlIERldGVjdCBTdGF0dXMi LAo+Pj4gKwkJLnR5cGUJPSBWNEwyX0NUUkxfVFlQRV9JTlRFR0VSLAo+Pj4gKwkJLm1pbgk9IFhT RElSWF9NT0RFX1NEX09GRlNFVCwKPj4+ICsJCS5tYXgJPSBYU0RJUlhfTU9ERV8xMkdGX09GRlNF VCwKPj4+ICsJCS5zdGVwCT0gMSwKPj4+ICsJCS5mbGFncyAgPSBWNEwyX0NUUkxfRkxBR19WT0xB VElMRSB8Cj4+IFY0TDJfQ1RSTF9GTEFHX1JFQURfT05MWSwKPj4+ICsJfSwgewo+Pj4gKwkJLm9w cwk9ICZ4c2Rpcnhzc19jdHJsX29wcywKPj4+ICsJCS5pZAk9IFY0TDJfQ0lEX1hJTElOWF9TRElS WF9DUkMsCj4+PiArCQkubmFtZQk9ICJTREkgUnggOiBDUkMgRXJyb3Igc3RhdHVzIiwKPj4+ICsJ CS50eXBlCT0gVjRMMl9DVFJMX1RZUEVfSU5URUdFUiwKPj4+ICsJCS5taW4JPSAwLAo+Pj4gKwkJ Lm1heAk9IDB4RkZGRkZGRkYsCj4+PiArCQkuc3RlcAk9IDEsCj4+PiArCQkuZGVmCT0gMCwKPj4+ ICsJCS5mbGFncyAgPSBWNEwyX0NUUkxfRkxBR19WT0xBVElMRSB8Cj4+IFY0TDJfQ1RSTF9GTEFH X1JFQURfT05MWSwKPj4+ICsJfSwgewo+Pj4gKwkJLm9wcwk9ICZ4c2Rpcnhzc19jdHJsX29wcywK Pj4+ICsJCS5pZAk9IFY0TDJfQ0lEX1hJTElOWF9TRElSWF9UU19JU19JTlRFUkxBQ0VELAo+Pj4g KwkJLm5hbWUJPSAiU0RJIFJ4IDogVFMgaXMgSW50ZXJsYWNlZCIsCj4+PiArCQkudHlwZQk9IFY0 TDJfQ1RSTF9UWVBFX0JPT0xFQU4sCj4+PiArCQkubWluCT0gZmFsc2UsCj4+PiArCQkubWF4CT0g dHJ1ZSwKPj4+ICsJCS5kZWYJPSBmYWxzZSwKPj4+ICsJCS5zdGVwCT0gMSwKPj4+ICsJCS5mbGFn cyAgPSBWNEwyX0NUUkxfRkxBR19WT0xBVElMRSB8Cj4+IFY0TDJfQ1RSTF9GTEFHX1JFQURfT05M WSwKPj4+ICsJfSwgewo+Pj4gKwkJLm9wcwk9ICZ4c2Rpcnhzc19jdHJsX29wcywKPj4+ICsJCS5p ZAk9IFY0TDJfQ0lEX1hJTElOWF9TRElSWF9BQ1RJVkVfU1RSRUFNUywKPj4+ICsJCS5uYW1lCT0g IlNESSBSeCA6IEFjdGl2ZSBTdHJlYW1zIiwKPj4+ICsJCS50eXBlCT0gVjRMMl9DVFJMX1RZUEVf SU5URUdFUiwKPj4+ICsJCS5taW4JPSAxLAo+Pj4gKwkJLm1heAk9IDE2LAo+Pj4gKwkJLmRlZgk9 IDEsCj4+PiArCQkuc3RlcAk9IDEsCj4+PiArCQkuZmxhZ3MgID0gVjRMMl9DVFJMX0ZMQUdfVk9M QVRJTEUgfAo+PiBWNEwyX0NUUkxfRkxBR19SRUFEX09OTFksCj4+PiArCX0sIHsKPj4+ICsJCS5v cHMJPSAmeHNkaXJ4c3NfY3RybF9vcHMsCj4+PiArCQkuaWQJPSBWNEwyX0NJRF9YSUxJTlhfU0RJ UlhfSVNfM0dCLAo+Pj4gKwkJLm5hbWUJPSAiU0RJIFJ4IDogSXMgM0dCIiwKPj4+ICsJCS50eXBl CT0gVjRMMl9DVFJMX1RZUEVfQk9PTEVBTiwKPj4+ICsJCS5taW4JPSBmYWxzZSwKPj4+ICsJCS5t YXgJPSB0cnVlLAo+Pj4gKwkJLmRlZgk9IGZhbHNlLAo+Pj4gKwkJLnN0ZXAJPSAxLAo+Pj4gKwkJ LmZsYWdzICA9IFY0TDJfQ1RSTF9GTEFHX1ZPTEFUSUxFIHwKPj4gVjRMMl9DVFJMX0ZMQUdfUkVB RF9PTkxZLAo+Pj4gKwl9Cj4+Cj4+IEFsbCB0aGVzZSBjb250cm9scyBuZWVkIHRvIGJlIGRvY3Vt ZW50ZWQgaW4gdGhlIGhlYWRlci4gU29tZSBvZiB0aGVzZSBjb250cm9scwo+PiBtYXkgdHVybiBv dXQgdG8gYmUgY29udHJvbHMgdGhhdCBjYW4gYmUgc3RhbmRhcmRpemVkIGZvciBTREkgcmVjZWl2 ZXJzLCBvdGhlcnMKPj4gbWlnaHQgYmUgbW9yZSB2ZW5kb3Igb3IgZHJpdmVyIHNwZWNpZmljLgo+ Pgo+IAo+IEkgaGF2ZSBkb2N1bWVudGVkIHRoZXNlIGluIHRoZSBoZWFkZXIuIEJ1dCBpdCBzZWVt cyBpbnN1ZmZpY2llbnQuIExldCBtZSBhZGQgbW9yZSBpbmZvIGluIGl0Lgo+IE1vc3Qgb2YgdGhp cyBpcyBJUCBzcGVjaWZpYy4gUHJvYmFibHkgTW9kZSBkZXRlY3RlZCBhbmQgQWN0aXZlIHN0cmVh bXMgY2FuIGJlIHN0YW5kYXJkaXplZC4KCkknbGwgcmV2aWV3IHRoaXMgc29tZSBtb3JlIHdoZW4g djMgaXMgcG9zdGVkLiBJdCdzIGxpa2VseSBJJ2xsIGRpc2N1c3MgdGhpcyBzb21lIG1vcmUKd2l0 aCB5b3UuCgo+IAo+Pj4gK307Cj4+PiArCj4+PiArc3RhdGljIGNvbnN0IHN0cnVjdCB2NGwyX3N1 YmRldl9jb3JlX29wcyB4c2Rpcnhzc19jb3JlX29wcyA9IHsKPj4+ICsJLmxvZ19zdGF0dXMgPSB4 c2Rpcnhzc19sb2dfc3RhdHVzLAo+Pj4gKwkuc3Vic2NyaWJlX2V2ZW50ID0geHNkaXJ4c3Nfc3Vi c2NyaWJlX2V2ZW50LAo+Pj4gKwkudW5zdWJzY3JpYmVfZXZlbnQgPSB4c2Rpcnhzc191bnN1YnNj cmliZV9ldmVudAo+Pj4gK307Cj4+PiArCj4+PiArc3RhdGljIGNvbnN0IHN0cnVjdCB2NGwyX3N1 YmRldl92aWRlb19vcHMgeHNkaXJ4c3NfdmlkZW9fb3BzID0gewo+Pj4gKwkuZ19mcmFtZV9pbnRl cnZhbCA9IHhzZGlyeHNzX2dfZnJhbWVfaW50ZXJ2YWwsCj4+PiArCS5zX3N0cmVhbSA9IHhzZGly eHNzX3Nfc3RyZWFtLAo+Pj4gKwkuZ19pbnB1dF9zdGF0dXMgPSB4c2Rpcnhzc19nX2lucHV0X3N0 YXR1cywKPj4+ICsJLnF1ZXJ5X2R2X3RpbWluZ3MgPSB4c2Rpcnhzc19xdWVyeV9kdl90aW1pbmdz LAo+Pgo+PiBUaGlzIGlzIG1pc3NpbmcgZy9zX2R2X3RpbWluZ3MuIFlvdSBuZWVkIHRvIGtlZXAg dHJhY2sgb2YgdGhlIGN1cnJlbnQKPj4gdGltaW5ncyBpbiB0aGUgZHJpdmVyIHN0YXRlOiB0eXBp Y2FsbHkgdXNlcnNwYWNlIHdpbGwgcXVlcnkgdGltaW5ncyBhbmQKPj4gaWYgdGhhdCByZXR1cm5z IHZhbGlkIHRpbWluZ3MgaXQgd2lsbCBzZXQgdGhlbSAoc19kdl90aW1pbmdzKS4gV2l0aAo+PiBn X2R2X3RpbWluZ3MgdGhlIGxhc3Qgc2V0IHRpbWluZ3MgYXJlIHJldHVybmVkLgo+Pgo+IAo+IFRo YW5rcyBmb3Igc2hhcmluZyB0aGlzIGluZm9ybWF0aW9uLiBJIGRpZG4ndCBnZXQgdGhlIHNlcXVl bmNlIGZyb20gdGhlIGN1cnJlbnQgZG9jdW1lbnRhdGlvbi4KPiBMZXQgbWUga25vdyBpZiB0aGVy ZSBpcyBhIHN0YW5kYXJkIGFwcGxpY2F0aW9uIHRoYXQgSSBtYXkgcmVmZXIgdG8gZm9yIHRoaXMu Cgp2NGwyLWN0bCBkb2VzIHRoaXMsIGFjdHVhbGx5LiBzdHJlYW1pbmdfc2V0X2NhcCgpIGluIHY0 bDItY3RsLXN0cmVhbWluZy5jcHAgaXMgd2hhdAppcyB1c2VkIHdoZW4geW91IHJ1biAndjRsMi1j dGwgLS1zdHJlYW0tbW1hcCcuCgo+IAo+PiBJZiB0aGUgdGltaW5ncyBjaGFuZ2UgdGhlbiB0aGUg ZHJpdmVyIHN0b3BzIHN0cmVhbWluZyBhbmQgcmVwb3J0cyB0aGUKPj4gU09VUkNFX0NIQU5HRSBl dmVudCwgYXQgd2hpY2ggcG9pbnQgdXNlcnNwYWNlIHdpbGwgcXVlcnkgdGhlIG5ldyB0aW1pbmdz Lgo+Pgo+IAo+IFRoZSBTT1VSQ0VfQ0hBTkdFIGV2ZW50IHdpbGwgYmUgZ2VuZXJhdGVkIG9ubHkg YWZ0ZXIgc3RvcHBpbmcgdGhlIHN0cmVhbWluZyB0byB0aGUgZG93bnN0cmVhbSBieQo+IGRpc2Fi bGluZyB0aGUgYnJpZGdlcy4gVGhlIGNvcmUgd2lsbCBhbHdheXMgYmUgZW5hYmxlZCB0byBkZXRl Y3QgYW55IG90aGVyIGluY29taW5nIHN0cmVhbS4gCj4gT25jZSBhIG5ldyBpbmNvbWluZyBzdHJl YW0gaXMgZGV0ZWN0ZWQgZm9yIHZpZGVvX2xvY2tfd2luZG93IGFtb3VudCBvZiB0aW1lLCAgYSB2 aWRlbyBsb2NrIGludGVycnVwdCBvY2N1cnMuCgpJIGRvbid0IHF1aXRlIHVuZGVyc3RhbmQgdGhp cy4KClRoZSBTT1VSQ0VfQ0hBTkdFIGV2ZW50IHNob3VsZCBiZSBpc3N1ZWQgd2hlbiB0aGUgZHJp dmVyIGRldGVjdHMgdGhhdCBpdApsb3N0IHNpZ25hbCwgb3IgYSBuZXcgc2lnbmFsIGFwcGVhcnMs IG9yIHRoZSBzdHJlYW0gY2hhbmdlcyByZXNvbHV0aW9uLgpJLmUuIGFsbCBjYXNlcyB3aGVyZSB1 c2Vyc3BhY2UgbmVlZHMgdG8gdGFrZSBhY3Rpb24uCgo+ICAKPj4gVGhlIHJlcG9ydGVkIG1lZGlh YnVzIGZvcm1hdCByZXNvbHV0aW9uIG9ubHkgY2hhbmdlcyB3aGVuIHNfZHZfdGltaW5ncwo+PiBp cyBjYWxsZWQ6IGl0J3MgdXBkYXRlZCB3aXRoIHRoZSBuZXcgd2lkdGgvaGVpZ2h0IGluZm8uCj4+ Cj4gCj4gSSB3aWxsIGNyZWF0ZSBhbm90aGVyIHY0bDJfbWJ1c19mcmFtZWZtdCBtZW1iZXIgaW4g dGhlIHN0YXRlIHN0cnVjdHVyZSB3aGljaCB3aWxsIGJlIHVwZGF0ZWQgd2l0aCB0aGUgZGV0ZWN0 ZWQgZm9ybWF0cyBpbiB0aGUgc19kdl90aW1pbmdzLgo+IFRoZW4gYXBwbGljYXRpb24gbWF5IGNh bGwgZ2V0L3NldF9mbXQoKS4gCj4gCj4+IEluIG90aGVyIHdvcmRzOiB0aGUgdGltaW5ncyByZXBv cnRlZCBieSBnX2R2X3RpbWluZ3MgYXJlIGNvbnRyb2xsZWQgYnkKPj4gdXNlcnNwYWNlLCB0aGUg dGltaW5ncyByZXBvcnRlZCBieSBxdWVyeV9kdl90aW1pbmdzIHJlZmxlY3QgdGhlIGFjdHVhbAo+ PiB0aW1pbmdzIHJlY2VpdmVkIG9uIHRoZSBTREkgYnVzLgo+Pgo+IAo+IFRoYW5rcyBmb3IgdGhp cyBkZXRhaWxlZCBleHBsYW5hdGlvbi4g8J+YiiAKPiAKPj4+ICt9Owo+Pj4gKwo+Pj4gK3N0YXRp YyBjb25zdCBzdHJ1Y3QgdjRsMl9zdWJkZXZfcGFkX29wcyB4c2Rpcnhzc19wYWRfb3BzID0gewo+ Pj4gKwkuaW5pdF9jZmcgPSB4c2Rpcnhzc19pbml0X2NmZywKPj4+ICsJLmdldF9mbXQgPSB4c2Rp cnhzc19nZXRfZm9ybWF0LAo+Pj4gKwkuc2V0X2ZtdCA9IHhzZGlyeHNzX3NldF9mb3JtYXQsCj4+ PiArCS5lbnVtX21idXNfY29kZSA9IHhzZGlyeHNzX2VudW1fbWJ1c19jb2RlLAo+Pj4gKwkuZW51 bV9kdl90aW1pbmdzID0geHNkaXJ4c3NfZW51bV9kdl90aW1pbmdzLAo+Pgo+PiBUaGlzIGlzIG1p c3NpbmcgZHZfdGltaW5nc19jYXAuCj4+Cj4gCj4gSSB3aWxsIGFkZCB0aGlzIGluIHRoZSBuZXh0 IHZlcnNpb24uCj4gCj4+PiArfTsKPj4+ICsKPj4+ICtzdGF0aWMgY29uc3Qgc3RydWN0IHY0bDJf c3ViZGV2X29wcyB4c2Rpcnhzc19vcHMgPSB7Cj4+PiArCS5jb3JlID0gJnhzZGlyeHNzX2NvcmVf b3BzLAo+Pj4gKwkudmlkZW8gPSAmeHNkaXJ4c3NfdmlkZW9fb3BzLAo+Pj4gKwkucGFkID0gJnhz ZGlyeHNzX3BhZF9vcHMKPj4+ICt9Owo+Pj4gKwo+Pj4gKy8qIC0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t Cj4+PiArICogUGxhdGZvcm0gRGV2aWNlIERyaXZlcgo+Pj4gKyAqLwo+Pj4gKwo+Pj4gK3N0YXRp YyBpbnQgeHNkaXJ4c3NfcGFyc2Vfb2Yoc3RydWN0IHhzZGlyeHNzX3N0YXRlICp4c2RpcnhzcykK Pj4+ICt7Cj4+PiArCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbm9kZSA9IHhzZGlyeHNzLT5jb3JlLmRl di0+b2Zfbm9kZTsKPj4+ICsJc3RydWN0IHhzZGlyeHNzX2NvcmUgKmNvcmUgPSAmeHNkaXJ4c3Mt PmNvcmU7Cj4+PiArCXN0cnVjdCBkZXZpY2UgKmRldiA9IGNvcmUtPmRldjsKPj4+ICsJc3RydWN0 IGZ3bm9kZV9oYW5kbGUgKmVwLCAqcmVwOwo+Pj4gKwlpbnQgcmV0Owo+Pj4gKwljb25zdCBjaGFy ICpzZGlfc3RkOwo+Pj4gKwo+Pj4gKwljb3JlLT5pbmNsdWRlX2VkaCA9IG9mX3Byb3BlcnR5X3Jl YWRfYm9vbChub2RlLCAieGxueCxpbmNsdWRlLWVkaCIpOwo+Pj4gKwlkZXZfZGJnKGRldiwgIkVE SCBwcm9wZXJ0eSA9ICVzXG4iLAo+Pj4gKwkJY29yZS0+aW5jbHVkZV9lZGggPyAiUHJlc2VudCIg OiAiQWJzZW50Iik7Cj4+PiArCj4+PiArCXJldCA9IG9mX3Byb3BlcnR5X3JlYWRfc3RyaW5nKG5v ZGUsICJ4bG54LGxpbmUtcmF0ZSIsICZzZGlfc3RkKTsKPj4+ICsJaWYgKHJldCA8IDApIHsKPj4+ ICsJCWRldl9lcnIoZGV2LCAieGxueCxsaW5lLXJhdGUgcHJvcGVydHkgbm90IGZvdW5kXG4iKTsK Pj4+ICsJCXJldHVybiByZXQ7Cj4+PiArCX0KPj4+ICsKPj4+ICsJaWYgKCFzdHJuY21wKHNkaV9z dGQsICIxMkdfU0RJXzhEUyIsIFhTRElSWF9NQVhfU1RSX0xFTkdUSCkpIHsKPj4+ICsJCWNvcmUt Pm1vZGUgPSBYU0RJUlhTU19TRElfU1REXzEyR184RFM7Cj4+PiArCX0gZWxzZSBpZiAoIXN0cm5j bXAoc2RpX3N0ZCwgIjZHX1NESSIsIFhTRElSWF9NQVhfU1RSX0xFTkdUSCkpIHsKPj4+ICsJCWNv cmUtPm1vZGUgPSBYU0RJUlhTU19TRElfU1REXzZHOwo+Pj4gKwl9IGVsc2UgaWYgKCFzdHJuY21w KHNkaV9zdGQsICIzR19TREkiLCBYU0RJUlhfTUFYX1NUUl9MRU5HVEgpKSB7Cj4+PiArCQljb3Jl LT5tb2RlID0gWFNESVJYU1NfU0RJX1NURF8zRzsKPj4+ICsJfSBlbHNlIHsKPj4+ICsJCWRldl9l cnIoZGV2LCAiSW52YWxpZCBMaW5lIFJhdGVcbiIpOwo+Pj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4+ PiArCX0KPj4+ICsJZGV2X2RiZyhkZXYsICJTREkgUnggTGluZSBSYXRlID0gJXMsIG1vZGUgPSAl ZFxuIiwgc2RpX3N0ZCwKPj4+ICsJCWNvcmUtPm1vZGUpOwo+Pj4gKwo+Pj4gKwlyZXQgPSBvZl9w cm9wZXJ0eV9yZWFkX3UzMihub2RlLCAieGxueCxicHAiLCAmY29yZS0+YnBjKTsKPj4+ICsJaWYg KHJldCA8IDApIHsKPj4+ICsJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRvIGdldCB4bG54LGJwcFxu Iik7Cj4+PiArCQlyZXR1cm4gcmV0Owo+Pj4gKwl9Cj4+PiArCj4+PiArCWlmIChjb3JlLT5icGMg IT0gMTAgJiYgY29yZS0+YnBjICE9IDEyKSB7Cj4+PiArCQlkZXZfZXJyKGRldiwgImJpdHMgcGVy IGNvbXBvbmVudD0ldS4gQ2FuIGJlIDEwIG9yIDEyIG9ubHlcbiIsCj4+PiArCQkJY29yZS0+YnBj KTsKPj4+ICsJCXJldHVybiAtRUlOVkFMOwo+Pj4gKwl9Cj4+PiArCj4+PiArCWVwID0gZndub2Rl X2dyYXBoX2dldF9lbmRwb2ludF9ieV9pZChkZXZfZndub2RlKGRldiksIDAsIDAsCj4+PiArCj4+ IEZXTk9ERV9HUkFQSF9FTkRQT0lOVF9ORVhUKTsKPj4+ICsJaWYgKCFlcCkgewo+Pj4gKwkJZGV2 X2VycihkZXYsICJubyBzb3VyY2UgcG9ydCBmb3VuZCIpOwo+Pj4gKwkJcmV0ID0gLUVJTlZBTDsK Pj4+ICsJCWdvdG8gZHRfcGFyc2VfZG9uZTsKPj4+ICsJfQo+Pj4gKwo+Pj4gKwlyZXAgPSBmd25v ZGVfZ3JhcGhfZ2V0X3JlbW90ZV9lbmRwb2ludChlcCk7Cj4+PiArCWlmICghcmVwKSB7Cj4+PiAr CQlkZXZfZXJyKGRldiwgIm5vIHJlbW90ZSBzaW5rIGVuZHBvaW50IGZvdW5kIik7Cj4+PiArCQly ZXQgPSAtRUlOVkFMOwo+Pj4gKwl9Cj4+PiArCj4+PiArCWZ3bm9kZV9oYW5kbGVfcHV0KHJlcCk7 Cj4+PiArZHRfcGFyc2VfZG9uZToKPj4+ICsJZndub2RlX2hhbmRsZV9wdXQoZXApOwo+Pj4gKwly ZXR1cm4gcmV0Owo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgaW50IHhzZGlyeHNzX3Byb2JlKHN0 cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4+PiArewo+Pj4gKwlzdHJ1Y3QgdjRsMl9zdWJk ZXYgKnN1YmRldjsKPj4+ICsJc3RydWN0IHhzZGlyeHNzX3N0YXRlICp4c2RpcnhzczsKPj4+ICsJ c3RydWN0IHhzZGlyeHNzX2NvcmUgKmNvcmU7Cj4+PiArCXN0cnVjdCBkZXZpY2UgKmRldjsKPj4+ ICsJaW50IHJldDsKPj4+ICsJdW5zaWduZWQgaW50IG51bV9jdHJscywgbnVtX2VkaF9jdHJscyA9 IDAsIGk7Cj4+PiArCj4+PiArCXhzZGlyeHNzID0gZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNp emVvZigqeHNkaXJ4c3MpLCBHRlBfS0VSTkVMKTsKPj4+ICsJaWYgKCF4c2RpcnhzcykKPj4+ICsJ CXJldHVybiAtRU5PTUVNOwo+Pj4gKwo+Pj4gKwl4c2Rpcnhzcy0+Y29yZS5kZXYgPSAmcGRldi0+ ZGV2Owo+Pj4gKwljb3JlID0gJnhzZGlyeHNzLT5jb3JlOwo+Pj4gKwlkZXYgPSBjb3JlLT5kZXY7 Cj4+PiArCj4+PiArCS8qIFJlZ2lzdGVyIGludGVycnVwdCBoYW5kbGVyICovCj4+PiArCWNvcmUt PmlycSA9IHBsYXRmb3JtX2dldF9pcnEocGRldiwgMCk7Cj4+PiArCXJldCA9IGRldm1fcmVxdWVz dF90aHJlYWRlZF9pcnEoZGV2LCBjb3JlLT5pcnEsIE5VTEwsCj4+PiArCQkJCQl4c2Rpcnhzc19p cnFfaGFuZGxlciwgSVJRRl9PTkVTSE9ULAo+Pj4gKwkJCQkJZGV2X25hbWUoZGV2KSwgeHNkaXJ4 c3MpOwo+Pj4gKwlpZiAocmV0KSB7Cj4+PiArCQlkZXZfZXJyKGRldiwgIkVyciA9ICVkIEludGVy cnVwdCBoYW5kbGVyIHJlZyBmYWlsZWQhXG4iLAo+Pj4gKwkJCXJldCk7Cj4+PiArCQlyZXR1cm4g cmV0Owo+Pj4gKwl9Cj4+PiArCj4+PiArCWNvcmUtPm51bV9jbGtzID0gQVJSQVlfU0laRSh4c2Rp cnhzc19jbGtzKTsKPj4+ICsJY29yZS0+Y2xrcyA9IGRldm1fa2NhbGxvYyhkZXYsIGNvcmUtPm51 bV9jbGtzLAo+Pj4gKwkJCQkgIHNpemVvZigqY29yZS0+Y2xrcyksIEdGUF9LRVJORUwpOwo+Pj4g KwlpZiAoIWNvcmUtPmNsa3MpCj4+PiArCQlyZXR1cm4gLUVOT01FTTsKPj4+ICsKPj4+ICsJZm9y IChpID0gMDsgaSA8IGNvcmUtPm51bV9jbGtzOyBpKyspCj4+PiArCQljb3JlLT5jbGtzW2ldLmlk ID0geHNkaXJ4c3NfY2xrc1tpXTsKPj4+ICsKPj4+ICsJcmV0ID0gZGV2bV9jbGtfYnVsa19nZXQo ZGV2LCBjb3JlLT5udW1fY2xrcywgY29yZS0+Y2xrcyk7Cj4+PiArCWlmIChyZXQpCj4+PiArCQly ZXR1cm4gcmV0Owo+Pj4gKwo+Pj4gKwlyZXQgPSBjbGtfYnVsa19wcmVwYXJlX2VuYWJsZShjb3Jl LT5udW1fY2xrcywgY29yZS0+Y2xrcyk7Cj4+PiArCWlmIChyZXQpCj4+PiArCQlyZXR1cm4gcmV0 Owo+Pj4gKwo+Pj4gKwlyZXQgPSB4c2Rpcnhzc19wYXJzZV9vZih4c2Rpcnhzcyk7Cj4+PiArCWlm IChyZXQgPCAwKQo+Pj4gKwkJZ290byBjbGtfZXJyOwo+Pj4gKwo+Pj4gKwljb3JlLT5pb21lbSA9 IGRldm1fcGxhdGZvcm1faW9yZW1hcF9yZXNvdXJjZShwZGV2LCAwKTsKPj4+ICsJaWYgKElTX0VS Uihjb3JlLT5pb21lbSkpIHsKPj4+ICsJCXJldCA9IFBUUl9FUlIoY29yZS0+aW9tZW0pOwo+Pj4g KwkJZ290byBjbGtfZXJyOwo+Pj4gKwl9Cj4+PiArCj4+PiArCS8qIFJlc2V0IHRoZSBjb3JlICov Cj4+PiArCXhzZGlyeF9zdHJlYW1mbG93X2NvbnRyb2woY29yZSwgZmFsc2UpOwo+Pj4gKwl4c2Rp cnhfY29yZV9kaXNhYmxlKGNvcmUpOwo+Pj4gKwl4c2RpcnhfY2xlYXJpbnRyKGNvcmUsIFhTRElS WF9JTlRSX0FMTF9NQVNLKTsKPj4+ICsJeHNkaXJ4X2Rpc2FibGVpbnRyKGNvcmUsIFhTRElSWF9J TlRSX0FMTF9NQVNLKTsKPj4+ICsJeHNkaXJ4X2VuYWJsZWludHIoY29yZSwgWFNESVJYX0lOVFJf QUxMX01BU0spOwo+Pj4gKwl4c2RpcnhfZ2xvYmFsaW50cihjb3JlLCB0cnVlKTsKPj4+ICsJeHNk aXJ4c3Nfd3JpdGUoY29yZSwgWFNESVJYX0NSQ19FUlJDTlRfUkVHLCAweEZGRkYpOwo+Pj4gKwo+ Pj4gKwkvKiBJbml0aWFsaXplIFY0TDIgc3ViZGV2aWNlIGFuZCBtZWRpYSBlbnRpdHkgKi8KPj4+ ICsJeHNkaXJ4c3MtPnBhZC5mbGFncyA9IE1FRElBX1BBRF9GTF9TT1VSQ0U7Cj4+PiArCj4+PiAr CS8qIEluaXRpYWxpemUgdGhlIGRlZmF1bHQgZm9ybWF0ICovCj4+PiArCWlmIChjb3JlLT5icGMg PT0gMTApCj4+PiArCQl4c2Rpcnhzcy0+ZGVmYXVsdF9mb3JtYXQuY29kZSA9Cj4+IE1FRElBX0JV U19GTVRfVVlWWTEwXzFYMjA7Cj4+PiArCWVsc2UKPj4+ICsJCXhzZGlyeHNzLT5kZWZhdWx0X2Zv cm1hdC5jb2RlID0KPj4gTUVESUFfQlVTX0ZNVF9VWVZZMTJfMVgyNDsKPj4+ICsJeHNkaXJ4c3Mt PmRlZmF1bHRfZm9ybWF0LmZpZWxkID0gVjRMMl9GSUVMRF9OT05FOwo+Pj4gKwl4c2Rpcnhzcy0+ ZGVmYXVsdF9mb3JtYXQuY29sb3JzcGFjZSA9IFY0TDJfQ09MT1JTUEFDRV9ERUZBVUxUOwo+Pgo+ PiBUaGlzIHNob3VsZG4ndCBiZSBERUZBVUxULiBDYW4geW91IGV4cGxhaW4gYSBiaXQgaG93IGNv bG9yc3BhY2UgKG9yCj4+IGNvbG9yaW1ldHJ5Cj4+IGluIGdlbmVyYWwpIGlzIGRldGVybWluZWQg Zm9yIFNEST8KPj4KPiAKPiBUaGF0IGlzIGNvcnJlY3QuIEFzIG1lbnRpb25lZCBlYXJsaWVyIHRo ZSBjb2xvcnNwYWNlIGluIFNESSBpcyBkZXRlcm1pbmVkIGJ5IGJpdCA1IGFuZCA0IG9mIGJ5dGUg MyAKPiBpbiB0aGUgNCBieXRlIFNUIDM1MiBwYXlsb2FkIGFzIHBlciBTTVBURSAyMDgxLTEwOjIw MTgKPiAKPiBiNTpiNCA9IDBoIGlkZW50aWZpZXMgUmVjIDcwOSBjb2xvcmltZXRyeSBpbiBhY2Nv cmRhbmNlIHdpdGggUmVjb21tZW5kYXRpb24gSVRVLVIgQlQuNzA5IGFzIHJlZmVyZW5jZWQgYnkg U01QVEUgU1QgMjc0Cj4gYjU6YjQgPSAxaCBpZGVudGlmaWVzIHRoYXQgdGhlIGNvbG9yaW1ldHJ5 IGlzIGRlZmluZWQgaW4gdGhlIENvbG9yIFZBTkMgcGFja2V0IGFzIGRlZmluZWQgaW4gU01QVEUg U1QgMjA0OC0xCj4gYjU6YjQgPSAyaCBpZGVudGlmaWVzIFVIRFRWIGNvbG9yaW1ldHJ5IGluIGFj Y29yZGFuY2Ugd2l0aCB0aGUgcmVmZXJlbmNlIHByaW1hcmllcyBhbmQgcmVmZXJlbmNlIHdoaXRl IGFzIGRlZmluZWQgaW4gU01QVEUgU1QgMjAzNi0xLiBTZWUgTm90ZSAyIHRvIFRhYmxlIDMuCj4g YjU6YjQgPSAzaCBpZGVudGlmaWVzIHVua25vd24gY29sb3JpbWV0cnkKCk9LLiBCYXNlZCBvbiB0 aGF0IEknZCBwaWNrIFJFQzcwOSBhcyB0aGUgZGVmYXVsdCBjb2xvcnNwYWNlLiBUaGlzIHdpbGwg YmUgdXBkYXRlZCB0bwp0aGUgYWN0dWFsIGNvbG9yc3BhY2Ugd2hlbiB5b3UgcmVjZWl2ZSBhIG5l dyB2aWRlbyBzdHJlYW0gYW5kIGNhbiBleHRyYWN0IHRoaXMgaW5mb3JtYXRpb24uCgo+IAo+Pj4g Kwl4c2Rpcnhzcy0+ZGVmYXVsdF9mb3JtYXQud2lkdGggPSBYU0RJUlhfREVGQVVMVF9XSURUSDsK Pj4+ICsJeHNkaXJ4c3MtPmRlZmF1bHRfZm9ybWF0LmhlaWdodCA9IFhTRElSWF9ERUZBVUxUX0hF SUdIVDsKPj4+ICsKPj4+ICsJeHNkaXJ4c3MtPmZvcm1hdCA9IHhzZGlyeHNzLT5kZWZhdWx0X2Zv cm1hdDsKPj4+ICsKPj4+ICsJLyogSW5pdGlhbGl6ZSBWNEwyIHN1YmRldmljZSBhbmQgbWVkaWEg ZW50aXR5ICovCj4+PiArCXN1YmRldiA9ICZ4c2Rpcnhzcy0+c3ViZGV2Owo+Pj4gKwl2NGwyX3N1 YmRldl9pbml0KHN1YmRldiwgJnhzZGlyeHNzX29wcyk7Cj4+PiArCj4+PiArCXN1YmRldi0+ZGV2 ID0gJnBkZXYtPmRldjsKPj4+ICsJc3Ryc2NweShzdWJkZXYtPm5hbWUsIGRldl9uYW1lKGRldiks IHNpemVvZihzdWJkZXYtPm5hbWUpKTsKPj4+ICsKPj4+ICsJc3ViZGV2LT5mbGFncyB8PSBWNEwy X1NVQkRFVl9GTF9IQVNfRVZFTlRTIHwKPj4gVjRMMl9TVUJERVZfRkxfSEFTX0RFVk5PREU7Cj4+ PiArCj4+PiArCXN1YmRldi0+ZW50aXR5Lm9wcyA9ICZ4c2Rpcnhzc19tZWRpYV9vcHM7Cj4+PiAr Cj4+PiArCXY0bDJfc2V0X3N1YmRldmRhdGEoc3ViZGV2LCB4c2Rpcnhzcyk7Cj4+PiArCj4+PiAr CXJldCA9IG1lZGlhX2VudGl0eV9wYWRzX2luaXQoJnN1YmRldi0+ZW50aXR5LCAxLCAmeHNkaXJ4 c3MtPnBhZCk7Cj4+PiArCWlmIChyZXQgPCAwKQo+Pj4gKwkJZ290byBlcnJvcjsKPj4+ICsKPj4+ ICsJLyogSW5pdGlhbGlzZSBhbmQgcmVnaXN0ZXIgdGhlIGNvbnRyb2xzICovCj4+PiArCW51bV9j dHJscyA9IEFSUkFZX1NJWkUoeHNkaXJ4c3NfY3RybHMpOwo+Pj4gKwo+Pj4gKwlpZiAoY29yZS0+ aW5jbHVkZV9lZGgpCj4+PiArCQludW1fZWRoX2N0cmxzID0gQVJSQVlfU0laRSh4c2Rpcnhzc19l ZGhfY3RybHMpOwo+Pj4gKwo+Pj4gKwl2NGwyX2N0cmxfaGFuZGxlcl9pbml0KCZ4c2Rpcnhzcy0+ Y3RybF9oYW5kbGVyLAo+Pj4gKwkJCSAgICAgICAobnVtX2N0cmxzICsgbnVtX2VkaF9jdHJscykp Owo+Pj4gKwo+Pj4gKwlmb3IgKGkgPSAwOyBpIDwgbnVtX2N0cmxzOyBpKyspIHsKPj4+ICsJCXN0 cnVjdCB2NGwyX2N0cmwgKmN0cmw7Cj4+PiArCj4+PiArCQlkZXZfZGJnKGRldiwgIiVkICVzIGN0 cmwgPSAweCV4XG4iLCBpLCB4c2Rpcnhzc19jdHJsc1tpXS5uYW1lLAo+Pj4gKwkJCXhzZGlyeHNz X2N0cmxzW2ldLmlkKTsKPj4+ICsKPj4+ICsJCWN0cmwgPSB2NGwyX2N0cmxfbmV3X2N1c3RvbSgm eHNkaXJ4c3MtPmN0cmxfaGFuZGxlciwKPj4+ICsJCQkJCSAgICAmeHNkaXJ4c3NfY3RybHNbaV0s IE5VTEwpOwo+Pj4gKwkJaWYgKCFjdHJsKSB7Cj4+PiArCQkJZGV2X2RiZyhkZXYsICJGYWlsZWQg dG8gYWRkICVzIGN0cmxcbiIsCj4+PiArCQkJCXhzZGlyeHNzX2N0cmxzW2ldLm5hbWUpOwo+Pj4g KwkJCWdvdG8gZXJyb3I7Cj4+PiArCQl9Cj4+PiArCX0KPj4+ICsKPj4+ICsJaWYgKGNvcmUtPmlu Y2x1ZGVfZWRoKSB7Cj4+PiArCQlmb3IgKGkgPSAwOyBpIDwgbnVtX2VkaF9jdHJsczsgaSsrKSB7 Cj4+PiArCQkJc3RydWN0IHY0bDJfY3RybCAqY3RybDsKPj4+ICsKPj4+ICsJCQlkZXZfZGJnKGRl diwgIiVkICVzIGN0cmwgPSAweCV4XG4iLCBpLAo+Pj4gKwkJCQl4c2Rpcnhzc19lZGhfY3RybHNb aV0ubmFtZSwKPj4+ICsJCQkJeHNkaXJ4c3NfZWRoX2N0cmxzW2ldLmlkKTsKPj4+ICsKPj4+ICsJ CQljdHJsID0gdjRsMl9jdHJsX25ld19jdXN0b20oJnhzZGlyeHNzLT5jdHJsX2hhbmRsZXIsCj4+ PiArCQkJCQkJICAgICZ4c2Rpcnhzc19lZGhfY3RybHNbaV0sCj4+PiArCQkJCQkJICAgIE5VTEwp Owo+Pj4gKwkJCWlmICghY3RybCkgewo+Pj4gKwkJCQlkZXZfZGJnKGRldiwgIkZhaWxlZCB0byBh ZGQgJXMgY3RybFxuIiwKPj4+ICsJCQkJCXhzZGlyeHNzX2VkaF9jdHJsc1tpXS5uYW1lKTsKPj4+ ICsJCQkJZ290byBlcnJvcjsKPj4+ICsJCQl9Cj4+PiArCQl9Cj4+PiArCX0KPj4+ICsKPj4+ICsJ aWYgKHhzZGlyeHNzLT5jdHJsX2hhbmRsZXIuZXJyb3IpIHsKPj4+ICsJCWRldl9lcnIoZGV2LCAi ZmFpbGVkIHRvIGFkZCBjb250cm9sc1xuIik7Cj4+PiArCQlyZXQgPSB4c2Rpcnhzcy0+Y3RybF9o YW5kbGVyLmVycm9yOwo+Pj4gKwkJZ290byBlcnJvcjsKPj4+ICsJfQo+Pj4gKwo+Pj4gKwlzdWJk ZXYtPmN0cmxfaGFuZGxlciA9ICZ4c2Rpcnhzcy0+Y3RybF9oYW5kbGVyOwo+Pj4gKwo+Pj4gKwly ZXQgPSB2NGwyX2N0cmxfaGFuZGxlcl9zZXR1cCgmeHNkaXJ4c3MtPmN0cmxfaGFuZGxlcik7Cj4+ PiArCWlmIChyZXQgPCAwKSB7Cj4+PiArCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBzZXQgY29u dHJvbHNcbiIpOwo+Pj4gKwkJZ290byBlcnJvcjsKPj4+ICsJfQo+Pj4gKwo+Pj4gKwlwbGF0Zm9y bV9zZXRfZHJ2ZGF0YShwZGV2LCB4c2Rpcnhzcyk7Cj4+PiArCj4+PiArCXJldCA9IHY0bDJfYXN5 bmNfcmVnaXN0ZXJfc3ViZGV2KHN1YmRldik7Cj4+PiArCWlmIChyZXQgPCAwKSB7Cj4+PiArCQlk ZXZfZXJyKGRldiwgImZhaWxlZCB0byByZWdpc3RlciBzdWJkZXZcbiIpOwo+Pj4gKwkJZ290byBl cnJvcjsKPj4+ICsJfQo+Pj4gKwo+Pj4gKwl4c2Rpcnhzcy0+c3RyZWFtaW5nID0gZmFsc2U7Cj4+ PiArCj4+PiArCXhzZGlyeF9jb3JlX2VuYWJsZShjb3JlKTsKPj4+ICsKPj4+ICsJZGV2X2luZm8o ZGV2LCAicHJvYmUgc3VjY2Vzc1xuIik7Cj4+PiArCj4+PiArCXJldHVybiAwOwo+Pj4gK2Vycm9y Ogo+Pj4gKwl2NGwyX2N0cmxfaGFuZGxlcl9mcmVlKCZ4c2Rpcnhzcy0+Y3RybF9oYW5kbGVyKTsK Pj4+ICsJbWVkaWFfZW50aXR5X2NsZWFudXAoJnN1YmRldi0+ZW50aXR5KTsKPj4+ICsJeHNkaXJ4 X2dsb2JhbGludHIoY29yZSwgZmFsc2UpOwo+Pj4gKwl4c2RpcnhfZGlzYWJsZWludHIoY29yZSwg WFNESVJYX0lOVFJfQUxMX01BU0spOwo+Pj4gK2Nsa19lcnI6Cj4+PiArCWNsa19idWxrX2Rpc2Fi bGVfdW5wcmVwYXJlKGNvcmUtPm51bV9jbGtzLCBjb3JlLT5jbGtzKTsKPj4+ICsJcmV0dXJuIHJl dDsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIGludCB4c2Rpcnhzc19yZW1vdmUoc3RydWN0IHBs YXRmb3JtX2RldmljZSAqcGRldikKPj4+ICt7Cj4+PiArCXN0cnVjdCB4c2Rpcnhzc19zdGF0ZSAq eHNkaXJ4c3MgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKPj4+ICsJc3RydWN0IHhzZGly eHNzX2NvcmUgKmNvcmUgPSAmeHNkaXJ4c3MtPmNvcmU7Cj4+PiArCXN0cnVjdCB2NGwyX3N1YmRl diAqc3ViZGV2ID0gJnhzZGlyeHNzLT5zdWJkZXY7Cj4+PiArCj4+PiArCXY0bDJfYXN5bmNfdW5y ZWdpc3Rlcl9zdWJkZXYoc3ViZGV2KTsKPj4+ICsJdjRsMl9jdHJsX2hhbmRsZXJfZnJlZSgmeHNk aXJ4c3MtPmN0cmxfaGFuZGxlcik7Cj4+PiArCW1lZGlhX2VudGl0eV9jbGVhbnVwKCZzdWJkZXYt PmVudGl0eSk7Cj4+PiArCj4+PiArCXhzZGlyeF9nbG9iYWxpbnRyKGNvcmUsIGZhbHNlKTsKPj4+ ICsJeHNkaXJ4X2Rpc2FibGVpbnRyKGNvcmUsIFhTRElSWF9JTlRSX0FMTF9NQVNLKTsKPj4+ICsJ eHNkaXJ4X2NvcmVfZGlzYWJsZShjb3JlKTsKPj4+ICsJeHNkaXJ4X3N0cmVhbWZsb3dfY29udHJv bChjb3JlLCBmYWxzZSk7Cj4+PiArCj4+PiArCWNsa19idWxrX2Rpc2FibGVfdW5wcmVwYXJlKGNv cmUtPm51bV9jbGtzLCBjb3JlLT5jbGtzKTsKPj4+ICsKPj4+ICsJcmV0dXJuIDA7Cj4+PiArfQo+ Pj4gKwo+Pj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIHhzZGlyeHNzX29mX2lk X3RhYmxlW10gPSB7Cj4+PiArCXsgLmNvbXBhdGlibGUgPSAieGxueCx2LXNtcHRlLXVoZHNkaS1y eC1zcy0yLjAiIH0sCj4+PiArCXsgfQo+Pj4gK307Cj4+PiArTU9EVUxFX0RFVklDRV9UQUJMRShv ZiwgeHNkaXJ4c3Nfb2ZfaWRfdGFibGUpOwo+Pj4gKwo+Pj4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZv cm1fZHJpdmVyIHhzZGlyeHNzX2RyaXZlciA9IHsKPj4+ICsJLmRyaXZlciA9IHsKPj4+ICsJCS5u YW1lCQk9ICJ4aWxpbngtc2RpcnhzcyIsCj4+PiArCQkub2ZfbWF0Y2hfdGFibGUJPSB4c2Rpcnhz c19vZl9pZF90YWJsZSwKPj4+ICsJfSwKPj4+ICsJLnByb2JlCQkJPSB4c2Rpcnhzc19wcm9iZSwK Pj4+ICsJLnJlbW92ZQkJCT0geHNkaXJ4c3NfcmVtb3ZlLAo+Pj4gK307Cj4+PiArCj4+PiArbW9k dWxlX3BsYXRmb3JtX2RyaXZlcih4c2Rpcnhzc19kcml2ZXIpOwo+Pj4gKwo+Pj4gK01PRFVMRV9B VVRIT1IoIlZpc2hhbCBTYWdhciA8dnNhZ2FyQHhpbGlueC5jb20+Iik7Cj4+PiArTU9EVUxFX0RF U0NSSVBUSU9OKCJYaWxpbnggU0RJIFJ4IFN1YnN5c3RlbSBEcml2ZXIiKTsKPj4+ICtNT0RVTEVf TElDRU5TRSgiR1BMIHYyIik7Cj4+PiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS91YXBpL2xpbnV4L3hp bGlueC1zZGlyeHNzLmggYi9pbmNsdWRlL3VhcGkvbGludXgveGlsaW54LQo+PiBzZGlyeHNzLmgK Pj4+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4+PiBpbmRleCAwMDAwMDAwMDAwMDAuLjZmMmEwOTM5 NjhkOQo+Pj4gLS0tIC9kZXYvbnVsbAo+Pj4gKysrIGIvaW5jbHVkZS91YXBpL2xpbnV4L3hpbGlu eC1zZGlyeHNzLmgKPj4+IEBAIC0wLDAgKzEsMTc5IEBACj4+PiArLyogU1BEWC1MaWNlbnNlLUlk ZW50aWZpZXI6IEdQTC0yLjAgV0lUSCBMaW51eC1zeXNjYWxsLW5vdGUgKi8KPj4+ICsvKgo+Pj4g KyAqIFhpbGlueCBTREkgUnggU3Vic3lzdGVtIG1vZGUsIGV2ZW50LCBjdXN0b20gdGltaW5ncwo+ Pj4gKyAqIGFuZCBmbGFnIGRlZmluaXRpb25zLgo+Pj4gKyAqCj4+PiArICogQ29weXJpZ2h0IChD KSAyMDE5IC0gMjAyMCBYaWxpbngsIEluYy4KPj4+ICsgKgo+Pj4gKyAqIENvbnRhY3RzOiBWaXNo YWwgU2FnYXIgPHZpc2hhbC5zYWdhckB4aWxpbnguY29tPgo+Pj4gKyAqLwo+Pj4gKwo+Pj4gKyNp Zm5kZWYgX19VQVBJX1hJTElOWF9TRElSWFNTX0hfXwo+Pj4gKyNkZWZpbmUgX19VQVBJX1hJTElO WF9TRElSWFNTX0hfXwo+Pj4gKwo+Pj4gKyNpbmNsdWRlIDxsaW51eC90eXBlcy5oPgo+Pj4gKyNp bmNsdWRlIDxsaW51eC92NGwyLWR2LXRpbWluZ3MuaD4KPj4+ICsjaW5jbHVkZSA8bGludXgvdmlk ZW9kZXYyLmg+Cj4+PiArCj4+PiArLyoKPj4+ICsgKiBFdmVudHMKPj4+ICsgKgo+Pj4gKyAqIFY0 TDJfRVZFTlRfWElMSU5YX1NESVJYX1VOREVSRkxPVzogVmlkZW8gaW4gdG8gQVhJNCBTdHJlYW0g Y29yZQo+PiB1bmRlcmZsb3dlZAo+Pj4gKyAqIFY0TDJfRVZFTlRfWElMSU5YX1NESVJYX09WRVJG TE9XOiBWaWRlbyBpbiB0byBBWEk0IFN0cmVhbSBjb3JlCj4+IG92ZXJmbG93ZWQKPj4+ICsgKi8K Pj4+ICsjZGVmaW5lIFY0TDJfRVZFTlRfWElMSU5YX1NESVJYX0NMQVNTCj4+IChWNEwyX0VWRU5U X1BSSVZBVEVfU1RBUlQgfCAweDIwMCkKPj4+ICsjZGVmaW5lIFY0TDJfRVZFTlRfWElMSU5YX1NE SVJYX1VOREVSRkxPVwo+PiAoVjRMMl9FVkVOVF9YSUxJTlhfU0RJUlhfQ0xBU1MgfCAweDEpCj4+ PiArI2RlZmluZSBWNEwyX0VWRU5UX1hJTElOWF9TRElSWF9PVkVSRkxPVwo+PiAoVjRMMl9FVkVO VF9YSUxJTlhfU0RJUlhfQ0xBU1MgfCAweDIpCj4+PiArCj4+PiArLyoKPj4+ICsgKiBUaGlzIGVu dW0gaXMgdXNlZCB0byBwcmVwYXJlIHRoZSBiaXRtYXNrIG9mIG1vZGVzIHRvIGJlIGRldGVjdGVk Cj4+PiArICovCj4+PiArZW51bSB7Cj4+PiArCVhTRElSWF9NT0RFX1NEX09GRlNFVCA9IDAsCj4+ PiArCVhTRElSWF9NT0RFX0hEX09GRlNFVCwKPj4+ICsJWFNESVJYX01PREVfM0dfT0ZGU0VULAo+ Pj4gKwlYU0RJUlhfTU9ERV82R19PRkZTRVQsCj4+PiArCVhTRElSWF9NT0RFXzEyR0lfT0ZGU0VU LAo+Pj4gKwlYU0RJUlhfTU9ERV8xMkdGX09GRlNFVCwKPj4+ICsJWFNESVJYX01PREVfTlVNX1NV UFBPUlRFRCwKPj4+ICt9Owo+Pj4gKwo+Pj4gKyNkZWZpbmUgWFNESVJYX0RFVEVDVF9BTExfTU9E RVMKPj4gCShCSVQoWFNESVJYX01PREVfU0RfT0ZGU0VUKSB8IFwKPj4+ICsJCQkJCUJJVChYU0RJ UlhfTU9ERV9IRF9PRkZTRVQpIHwgXAo+Pj4gKwkJCQkJQklUKFhTRElSWF9NT0RFXzNHX09GRlNF VCkgfCBcCj4+PiArCQkJCQlCSVQoWFNESVJYX01PREVfNkdfT0ZGU0VUKSB8IFwKPj4+ICsJCQkJ CUJJVChYU0RJUlhfTU9ERV8xMkdJX09GRlNFVCkgfCBcCj4+PiArCQkJCQlCSVQoWFNESVJYX01P REVfMTJHRl9PRkZTRVQpKQo+Pj4gKwo+Pj4gKy8qCj4+PiArICogRURIIEVycm9yIFR5cGVzCj4+ PiArICogQU5DIC0gQW5jaWxsYXJ5IERhdGEgUGFja2V0IEVycm9ycwo+Pj4gKyAqIEZGIC0gRnVs bCBGaWVsZCBFcnJvcnMKPj4+ICsgKiBBUCAtIEFjdGl2ZSBQb3J0aW9uIEVycm9ycwo+Pj4gKyAq Lwo+Pj4gKwo+Pj4gKyNkZWZpbmUgWFNESVJYX0VESF9FUlJDTlRfQU5DX0VESF9FUlIJCUJJVCgw KQo+Pj4gKyNkZWZpbmUgWFNESVJYX0VESF9FUlJDTlRfQU5DX0VEQV9FUlIJCUJJVCgxKQo+Pj4g KyNkZWZpbmUgWFNESVJYX0VESF9FUlJDTlRfQU5DX0lESF9FUlIJCUJJVCgyKQo+Pj4gKyNkZWZp bmUgWFNESVJYX0VESF9FUlJDTlRfQU5DX0lEQV9FUlIJCUJJVCgzKQo+Pj4gKyNkZWZpbmUgWFNE SVJYX0VESF9FUlJDTlRfQU5DX1VFU19FUlIJCUJJVCg0KQo+Pj4gKyNkZWZpbmUgWFNESVJYX0VE SF9FUlJDTlRfRkZfRURIX0VSUgkJQklUKDUpCj4+PiArI2RlZmluZSBYU0RJUlhfRURIX0VSUkNO VF9GRl9FREFfRVJSCQlCSVQoNikKPj4+ICsjZGVmaW5lIFhTRElSWF9FREhfRVJSQ05UX0ZGX0lE SF9FUlIJCUJJVCg3KQo+Pj4gKyNkZWZpbmUgWFNESVJYX0VESF9FUlJDTlRfRkZfSURBX0VSUgkJ QklUKDgpCj4+PiArI2RlZmluZSBYU0RJUlhfRURIX0VSUkNOVF9GRl9VRVNfRVJSCQlCSVQoOSkK Pj4+ICsjZGVmaW5lIFhTRElSWF9FREhfRVJSQ05UX0FQX0VESF9FUlIJCUJJVCgxMCkKPj4+ICsj ZGVmaW5lIFhTRElSWF9FREhfRVJSQ05UX0FQX0VEQV9FUlIJCUJJVCgxMSkKPj4+ICsjZGVmaW5l IFhTRElSWF9FREhfRVJSQ05UX0FQX0lESF9FUlIJCUJJVCgxMikKPj4+ICsjZGVmaW5lIFhTRElS WF9FREhfRVJSQ05UX0FQX0lEQV9FUlIJCUJJVCgxMykKPj4+ICsjZGVmaW5lIFhTRElSWF9FREhf RVJSQ05UX0FQX1VFU19FUlIJCUJJVCgxNCkKPj4+ICsjZGVmaW5lIFhTRElSWF9FREhfRVJSQ05U X1BLVF9DSEtTVU1fRVJSCUJJVCgxNSkKPj4+ICsKPj4+ICsjZGVmaW5lIFhTRElSWF9FREhfQUxM RVJSX01BU0sJCTB4RkZGRgo+Pj4gKwo+Pj4gKy8qIFhpbGlueCBEViB0aW1pbmdzIG5vdCBpbiBt YWlubGluZSB5ZXQgKi8KPj4+ICsjZGVmaW5lIFhMTlhfVjRMMl9EVl9CVF8yMDQ4WDEwODBQMjQg eyBcCj4+PiArCS50eXBlID0gVjRMMl9EVl9CVF82NTZfMTEyMCwgXAo+Pj4gKwlWNEwyX0lOSVRf QlRfVElNSU5HUygyMDQ4LCAxMDgwLCAwLCBcCj4+PiArCQlWNEwyX0RWX0hTWU5DX1BPU19QT0wg fCBWNEwyX0RWX1ZTWU5DX1BPU19QT0wsIFwKPj4+ICsJCTc0MjUwMDAwLCA1MTAsIDQ0LCAxNDgs IDQsIDUsIDM2LCAwLCAwLCAwLCBcCj4+PiArCQlWNEwyX0RWX0JUX1NURF9TREkpIFwKPj4+ICt9 Cj4+PiArCj4+PiArI2RlZmluZSBYTE5YX1Y0TDJfRFZfQlRfMjA0OFgxMDgwUDI1IHsgXAo+Pj4g KwkudHlwZSA9IFY0TDJfRFZfQlRfNjU2XzExMjAsIFwKPj4+ICsJVjRMMl9JTklUX0JUX1RJTUlO R1MoMjA0OCwgMTA4MCwgMCwgXAo+Pj4gKwkJVjRMMl9EVl9IU1lOQ19QT1NfUE9MIHwgVjRMMl9E Vl9WU1lOQ19QT1NfUE9MLCBcCj4+PiArCQk3NDI1MDAwMCwgNDAwLCA0NCwgMTQ4LCA0LCA1LCAz NiwgMCwgMCwgMCwgXAo+Pj4gKwkJVjRMMl9EVl9CVF9TVERfU0RJKSBcCj4+PiArfQo+Pj4gKwo+ Pj4gKyNkZWZpbmUgWExOWF9WNEwyX0RWX0JUXzIwNDhYMTA4MFAzMCB7IFwKPj4+ICsJLnR5cGUg PSBWNEwyX0RWX0JUXzY1Nl8xMTIwLCBcCj4+PiArCVY0TDJfSU5JVF9CVF9USU1JTkdTKDIwNDgs IDEwODAsIDAsIFwKPj4+ICsJCVY0TDJfRFZfSFNZTkNfUE9TX1BPTCB8IFY0TDJfRFZfVlNZTkNf UE9TX1BPTCwgXAo+Pj4gKwkJNzQyNTAwMDAsIDY2LCAyMCwgNjYsIDQsIDUsIDM2LCAwLCAwLCAw LCBcCj4+PiArCQlWNEwyX0RWX0JUX1NURF9TREkpIFwKPj4+ICt9Cj4+PiArCj4+PiArI2RlZmlu ZSBYTE5YX1Y0TDJfRFZfQlRfMjA0OFgxMDgwSTQ4IHsgXAo+Pj4gKwkudHlwZSA9IFY0TDJfRFZf QlRfNjU2XzExMjAsIFwKPj4+ICsJVjRMMl9JTklUX0JUX1RJTUlOR1MoMjA0OCwgMTA4MCwgMSwg XAo+Pj4gKwkJVjRMMl9EVl9IU1lOQ19QT1NfUE9MIHwgVjRMMl9EVl9WU1lOQ19QT1NfUE9MLCBc Cj4+PiArCQk3NDI1MDAwMCwgMzI5LCA0NCwgMzI5LCAyLCA1LCAxNSwgMywgNSwgMTUsIFwKPj4+ ICsJCVY0TDJfRFZfQlRfU1REX1NESSkgXAo+Pj4gK30KPj4+ICsKPj4+ICsjZGVmaW5lIFhMTlhf VjRMMl9EVl9CVF8yMDQ4WDEwODBJNTAgeyBcCj4+PiArCS50eXBlID0gVjRMMl9EVl9CVF82NTZf MTEyMCwgXAo+Pj4gKwlWNEwyX0lOSVRfQlRfVElNSU5HUygyMDQ4LCAxMDgwLCAxLCBcCj4+PiAr CQlWNEwyX0RWX0hTWU5DX1BPU19QT0wgfCBWNEwyX0RWX1ZTWU5DX1BPU19QT0wsIFwKPj4+ICsJ CTc0MjUwMDAwLCAyNzQsIDQ0LCAyNzQsIDIsIDUsIDE1LCAzLCA1LCAxNSwgXAo+Pj4gKwkJVjRM Ml9EVl9CVF9TVERfU0RJKSBcCj4+PiArfQo+Pj4gKwo+Pj4gKyNkZWZpbmUgWExOWF9WNEwyX0RW X0JUXzIwNDhYMTA4MEk2MCB7IFwKPj4+ICsJLnR5cGUgPSBWNEwyX0RWX0JUXzY1Nl8xMTIwLCBc Cj4+PiArCVY0TDJfSU5JVF9CVF9USU1JTkdTKDIwNDgsIDEwODAsIDEsIFwKPj4+ICsJCVY0TDJf RFZfSFNZTkNfUE9TX1BPTCB8IFY0TDJfRFZfVlNZTkNfUE9TX1BPTCwgXAo+Pj4gKwkJNzQyNTAw MDAsIDY2LCAyMCwgNjYsIDIsIDUsIDE1LCAzLCA1LCAxNSwgXAo+Pj4gKwkJVjRMMl9EVl9CVF9T VERfU0RJKSBcCj4+PiArfQo+Pj4gKwo+Pj4gKyNkZWZpbmUgWExOWF9WNEwyX0RWX0JUXzE5MjBY MTA4MFA0OCB7IFwKPj4+ICsJLnR5cGUgPSBWNEwyX0RWX0JUXzY1Nl8xMTIwLCBcCj4+PiArCVY0 TDJfSU5JVF9CVF9USU1JTkdTKDE5MjAsIDEwODAsIDAsIFwKPj4+ICsJCVY0TDJfRFZfSFNZTkNf UE9TX1BPTCB8IFY0TDJfRFZfVlNZTkNfUE9TX1BPTCwgXAo+Pj4gKwkJMTQ4NTAwMDAwLCA2Mzgs IDQ0LCAxNDgsIDQsIDUsIDM2LCAwLCAwLCAwLCBcCj4+PiArCQlWNEwyX0RWX0JUX1NURF9TREkp IFwKPj4+ICt9Cj4+PiArCj4+PiArI2RlZmluZSBYTE5YX1Y0TDJfRFZfQlRfMjA0OFgxMDgwUDQ4 IHsgXAo+Pj4gKwkudHlwZSA9IFY0TDJfRFZfQlRfNjU2XzExMjAsIFwKPj4+ICsJVjRMMl9JTklU X0JUX1RJTUlOR1MoMjA0OCwgMTA4MCwgMCwgXAo+Pj4gKwkJVjRMMl9EVl9IU1lOQ19QT1NfUE9M IHwgVjRMMl9EVl9WU1lOQ19QT1NfUE9MLCBcCj4+PiArCQkxNDg1MDAwMDAsIDUxMCwgNDQsIDE0 OCwgNCwgNSwgMzYsIDAsIDAsIDAsIFwKPj4+ICsJCVY0TDJfRFZfQlRfU1REX1NESSkgXAo+Pj4g K30KPj4+ICsKPj4+ICsjZGVmaW5lIFhMTlhfVjRMMl9EVl9CVF8yMDQ4WDEwODBQNTAgeyBcCj4+ PiArCS50eXBlID0gVjRMMl9EVl9CVF82NTZfMTEyMCwgXAo+Pj4gKwlWNEwyX0lOSVRfQlRfVElN SU5HUygyMDQ4LCAxMDgwLCAwLCBcCj4+PiArCQlWNEwyX0RWX0hTWU5DX1BPU19QT0wgfCBWNEwy X0RWX1ZTWU5DX1BPU19QT0wsIFwKPj4+ICsJCTE0ODUwMDAwMCwgNDAwLCA0NCwgMTQ4LCA0LCA1 LCAzNiwgMCwgMCwgMCwgXAo+Pj4gKwkJVjRMMl9EVl9CVF9TVERfU0RJKSBcCj4+PiArfQo+Pj4g Kwo+Pj4gKyNkZWZpbmUgWExOWF9WNEwyX0RWX0JUXzIwNDhYMTA4MFA2MCB7IFwKPj4+ICsJLnR5 cGUgPSBWNEwyX0RWX0JUXzY1Nl8xMTIwLCBcCj4+PiArCVY0TDJfSU5JVF9CVF9USU1JTkdTKDIw NDgsIDEwODAsIDAsIFwKPj4+ICsJCVY0TDJfRFZfSFNZTkNfUE9TX1BPTCB8IFY0TDJfRFZfVlNZ TkNfUE9TX1BPTCwgXAo+Pj4gKwkJMTQ4NTAwMDAwLCA4OCwgNDQsIDIwLCA0LCA1LCAzNiwgMCwg MCwgMCwgXAo+Pj4gKwkJVjRMMl9EVl9CVF9TVERfU0RJKSBcCj4+PiArfQo+Pj4gKwo+Pj4gKyNk ZWZpbmUgWExOWF9WNEwyX0RWX0JUXzM4NDBYMjE2MFA0OCB7IFwKPj4+ICsJLnR5cGUgPSBWNEwy X0RWX0JUXzY1Nl8xMTIwLCBcCj4+PiArCVY0TDJfSU5JVF9CVF9USU1JTkdTKDM4NDAsIDIxNjAs IDAsIFwKPj4+ICsJCVY0TDJfRFZfSFNZTkNfUE9TX1BPTCB8IFY0TDJfRFZfVlNZTkNfUE9TX1BP TCwgXAo+Pj4gKwkJNTk0MDAwMDAwLCAxMjc2LCA4OCwgMjk2LCA4LCAxMCwgNzIsIDAsIDAsIDAs IFwKPj4+ICsJCVY0TDJfRFZfQlRfU1REX1NESSkgXAo+Pj4gK30KPj4+ICsKPj4+ICsjZGVmaW5l IFhMTlhfVjRMMl9EVl9CVF80MDk2WDIxNjBQNDggeyBcCj4+PiArCS50eXBlID0gVjRMMl9EVl9C VF82NTZfMTEyMCwgXAo+Pj4gKwlWNEwyX0lOSVRfQlRfVElNSU5HUyg0MDk2LCAyMTYwLCAwLCBc Cj4+PiArCQlWNEwyX0RWX0hTWU5DX1BPU19QT0wgfCBWNEwyX0RWX1ZTWU5DX1BPU19QT0wsIFwK Pj4+ICsJCTU5NDAwMDAwMCwgMTAyMCwgODgsIDI5NiwgOCwgMTAsIDcyLCAwLCAwLCAwLCBcCj4+ PiArCQlWNEwyX0RWX0JUX1NURF9TREkpIFwKPj4+ICt9Cj4+PiArCj4+PiArI2RlZmluZSBYTE5Y X1Y0TDJfRFZfQlRfMTkyMFgxMDgwSTQ4IHsgXAo+Pj4gKwkudHlwZSA9IFY0TDJfRFZfQlRfNjU2 XzExMjAsIFwKPj4+ICsJVjRMMl9JTklUX0JUX1RJTUlOR1MoMTkyMCwgMTA4MCwgMSwgXAo+Pj4g KwkJVjRMMl9EVl9IU1lOQ19QT1NfUE9MIHwgVjRMMl9EVl9WU1lOQ19QT1NfUE9MLCBcCj4+PiAr CQkxNDg1MDAwMDAsIDM3MSwgODgsIDM3MSwgMiwgNSwgMTUsIDMsIDUsIDE1LCBcCj4+PiArCQlW NEwyX0RWX0JUX1NURF9TREkpIFwKPj4+ICt9Cj4+Cj4+IFdoeSBub3QgYWRkIHRoZXNlIHRvIHY0 bDItZHYtdGltaW5ncy5oPyBJIGRvIG5lZWQgdG8ga25vdyBvbiB3aGljaCBzdGFuZGFyZAo+PiB0 aGV5IGFyZSBiYXNlZC4KPj4KPiAKPiBDdXJyZW50bHkgdGhlc2UgYXJlIGJhc2VkIG9mZiBhIHRp bWluZyB0YWJsZSB1c2VkIGluIHRoZSBjb3JyZXNwb25kaW5nIGJhcmUgbWV0YWwgZHJpdmVyLgo+ IEkgd2lsbCB0cnkgdG8gZ2V0IHRoZSBzdGFuZGFyZHMgZnJvbSB3aGljaCB0aGVzZSBhcmUgYmFz ZWQgb24uCj4gTWVhbndoaWxlIEkgaG9wZSBpdCBpcyBvayB0byBhZGQgdGhlbSBhcyBjdXN0b20g dGltaW5ncy4KCkZvciBub3csIGJ1dCB0aGlzIHJlYWxseSBuZWVkcyB0byBiZSBzb3J0ZWQuIFRo ZSAyMDQ4eDEwODAgdGltaW5ncyBhcHBlYXIgdG8gYmUKRENJIERpZ2l0YWwgQ2luZW1hIHJlbGF0 ZWQuIDM4NDB4MjE2MHA0OCBpcyBhIENUQS04NjEgdGltaW5nIChWSUMgMTE0KSBhbmQKNDA5Nngy MTYwcDQ4IGlzIFZJQyAxMTUuIEknbSBub3Qgc3VyZSB3aGVyZSB0aGUgMTkyMHgxMDgwaTQ4IHRp bWluZ3MgY29tZSBmcm9tLgoKVGhlIHR3byBDVEEtZGVyaXZlZCB0aW1pbmdzIGNhbiBkZWZpbml0 ZWx5IGJlIGFkZGVkIHRvIHY0bDItZHYtdGltaW5ncy5oLgoKPiAKPj4+ICsKPj4+ICsjZW5kaWYg LyogX19VQVBJX1hJTElOWF9TRElSWFNTX0hfXyAqLwo+Pj4gZGlmZiAtLWdpdCBhL2luY2x1ZGUv dWFwaS9saW51eC94aWxpbngtdjRsMi1jb250cm9scy5oCj4+IGIvaW5jbHVkZS91YXBpL2xpbnV4 L3hpbGlueC12NGwyLWNvbnRyb2xzLmgKPj4+IGluZGV4IGI2NDQxZmU3MDVjNS4uZTlkZTY1ZTgy NjQyIDEwMDY0NAo+Pj4gLS0tIGEvaW5jbHVkZS91YXBpL2xpbnV4L3hpbGlueC12NGwyLWNvbnRy b2xzLmgKPj4+ICsrKyBiL2luY2x1ZGUvdWFwaS9saW51eC94aWxpbngtdjRsMi1jb250cm9scy5o Cj4+Cj4+IFdoeSBpcyB0aGlzIGluIGEgc2VwYXJhdGUgaGVhZGVyPyBJdCBzZWVtcyB0byBtZSB0 aGF0IGl0IG1ha2VzIG1vcmUgc2Vuc2UgdG8KPj4gaGF2ZQo+PiBhIHNpbmdsZSBwdWJsaWMgaGVh ZGVyIGZvciB0aGlzIGRyaXZlci4KPj4KPiAKPiBJIHRoaW5rIHRoZSB4aWxpbngtdjRsMi1jb250 cm9scy5oIGlzIGNyZWF0ZWQgdG8gaG91c2UgYWxsIGN1c3RvbSBjb250cm9scyBvZiBYaWxpbngg VjRMMiBkcml2ZXJzLgo+IFNpbmNlIHRoZSBYaWxpbnggVmlkZW8gVGVzdCBQYXR0ZXJuIGdlbmVy YXRvciBoYXMgaXRzIGNvbnRyb2xzIGluIHRoZSB4aWxpbngtdjRsMi1jb250cm9scy5oLAo+IEkg ZGVjaWRlZCB0byBrZWVwIHRoZSBjb250cm9scyBpbiB0aGlzIGZpbGUgYW5kIHRoZSBldmVudHMg aW4gdGhlIFNESSBSeCBzcGVjaWZpYyBoZWFkZXIuCgpTbyB0aGUgVFBHIGNvbnRyb2xzIGFyZSBz aGFyZWQgYmV0d2VlbiBkaWZmZXJlbnQgeGlsaW54IElQIGJsb2Nrcz8KCkFzc3VtaW5nIHRoYXQg dGhlIGNvbnRyb2xzIHlvdSBhZGQgaGVyZSBmb3IgeW91ciBkcml2ZXIgYXJlIHNwZWNpZmljIHRv IGp1c3QgdGhpcwpJUCBibG9jaywgSSB3b3VsZCBhZGQgdGhlbSB0byB4aWxpbngtc2Rpcnhzcy5o IGluc3RlYWQuCgpMb29raW5nIGF0IHhpbGlueC12NGwyLWNvbnRyb2xzLmg6IGl0IHNob3VsZG4n dCBzZXQgVjRMMl9DSURfWElMSU5YX09GRlNFVC9CQVNFIGhlcmUsCmluc3RlYWQgaXQgc2hvdWxk IHJlc2VydmUgdGhlIHJhbmdlIGluIHY0bDItY29udHJvbHMuaC4gVGhpcyB0byBlbnN1cmUgQ0lE cyByZXNlcnZlZApoZXJlIGRvIG5vdCBjbGFzaCB3aXRoIG90aGVyIENJRHMgcmVzZXJ2ZWQgYnkg b3RoZXIgZHJpdmVycy4KCkZvciB0aGUgY29udHJvbHMgc3BlY2lmaWMgdG8gdGhpcyBkcml2ZXIg SSB3b3VsZCBhbHNvIHJlc2VydmUgeW91ciBvd24gcmFuZ2UgaW4KdjRsMi1jb250cm9scy5oLCBy YXRoZXIgdGhhbiB0YWtpbmcgaXQgZnJvbSB0aGUgcmFuZ2UgcmVzZXJ2ZWQgYnkgeGlsaW54LXY0 bDItY29udHJvbHMuaC4KClJlZ2FyZHMsCgoJSGFucwoKPiAKPj4+IEBAIC03MSw0ICs3MSw3MSBA QAo+Pj4gIC8qIE5vaXNlIGxldmVsICovCj4+PiAgI2RlZmluZSBWNEwyX0NJRF9YSUxJTlhfVFBH X05PSVNFX0dBSU4KPj4gCShWNEwyX0NJRF9YSUxJTlhfVFBHICsgMTcpCj4+Pgo+Pj4gKy8qCj4+ PiArICogWGlsaW54IFNESSBSeCBTdWJzeXN0ZW0KPj4+ICsgKi8KPj4+ICsKPj4+ICsvKiBUaGUg YmFzZSBmb3IgdGhlIHNkaSByeCBkcml2ZXIgY29udHJvbHMuCj4+PiArICogV2UgcmVzZXJ2ZSAz MiBjb250cm9scyBmb3IgdGhpcyBkcml2ZXIuCj4+PiArICoKPj4+ICsgKiBUaGUgVjRMMl9DSURf WElMSU5YX1NESVJYX0VESF8qIGNvbnRyb2xzIGFyZSBwcmVzZW50IG9ubHkgaWYKPj4+ICsgKiBF REggaXMgZW5hYmxlZC4KPj4+ICsgKiBUaGUgY29udHJvbHMgd2hpY2ggY2FuIGJlIHNldCBzaG91 bGQgb25seSBiZSBzZXQgYmVmb3JlIGVuYWJsaW5nCj4+PiArICogc3RyZWFtaW5nLiBUaGUgY29u dHJvbHMgd2hpY2ggY2FuIGJlIGdvdCBzaG91bGQgYmUgY2FsbGVkIHdoaWxlCj4+PiArICogc3Ry ZWFtaW5nIHRvIGdldCBjb3JyZWN0IHZhbHVlcy4KPj4+ICsgKiBUaGUgVjRMMl9DSURfWElMSU5Y X1NESVJYX01PREVfREVURUNUIGNhbiBiZSBjYWxsZWQgd2hlbiBxdWVyeQo+PiBkdiB0aW1pbmcK Pj4+ICsgKiByZXR1cm5zIGEgdmFsaWQgdGltaW5nLgo+Pj4gKyAqLwo+Pj4gKwo+Pj4gKyNkZWZp bmUgVjRMMl9DSURfWElMSU5YX1NESVJYCj4+IAkoVjRMMl9DSURfWElMSU5YX0JBU0UgKyAweDIw KQo+Pj4gKwo+Pj4gKy8qIEZyYW1lciBDb250cm9sIHRvIGVuYWJsZSBvciBkaXNhYmxlIHRoZSBm cmFtZXIgKi8KPj4+ICsjZGVmaW5lIFY0TDJfQ0lEX1hJTElOWF9TRElSWF9GUkFNRVIKPj4gCShW NEwyX0NJRF9YSUxJTlhfU0RJUlggKyAxKQo+Pj4gKy8qCj4+PiArICogVmlkZW8gTG9jayBXaW5k b3cgQ29udHJvbCB0byBzZXQgdGhlIHZpZGVvIGxvY2sgd2luZG93IHZhbHVlCj4+PiArICogVGhp cyBpcyB0aGUgYW1vdW50IG9mIHRpbWUgdGhlIG1vZGUgYW5kIHRyYW5zcG9ydCBzdHJlYW0gbmVl ZAo+Pj4gKyAqIHRvIGJlIGxvY2tlZCBiZWZvcmUgYSB2aWRlbyBsb2NrIGludGVycnVwdCBvY2N1 cnMuCj4+PiArICovCj4+PiArI2RlZmluZSBWNEwyX0NJRF9YSUxJTlhfU0RJUlhfVklETE9DS19X SU5ET1cKPj4gCShWNEwyX0NJRF9YSUxJTlhfU0RJUlggKyAyKQo+Pj4gKy8qIEVESCBFcnJvciBN YXNrIENvbnRyb2wgdG8gZW5hYmxlIEVESCBlcnJvciBjb3VudCAqLwo+Pj4gKyNkZWZpbmUgVjRM Ml9DSURfWElMSU5YX1NESVJYX0VESF9FUlJDTlRfRU5BQkxFCj4+IAkoVjRMMl9DSURfWElMSU5Y X1NESVJYICsgMykKPj4+ICsvKgo+Pj4gKyAqIE1vZGUgc2VhcmNoIENvbnRyb2wgdG8gcGFzcyB0 aGUgYml0IG1hc2sgb2YgbW9kZXMgdG8gZGV0ZWN0Lgo+Pj4gKyAqCj4+PiArICogYml0IDAgc2V0 IHRvIGRldGVjdCBTRCBtb2RlLAo+Pj4gKyAqIGJpdCAxIHNldCB0byBkZXRlY3QgSEQgbW9kZSwK Pj4+ICsgKiBiaXQgMiBzZXQgdG8gZGV0ZWN0IDNHICgzR0EgJiAzR0IpIG1vZGUsCj4+PiArICog Yml0IDMgc2V0IHRvIGRldGVjdCA2RyBtb2RlLAo+Pj4gKyAqIGJpdCA0IHNldCB0byBkZXRlY3Qg MTJHIGludGVnZXIgZnJhbWUgcmF0ZSBtb2RlLAo+Pj4gKyAqIGJpdCA1IHNldCB0byBkZXRlY3Qg MTJHIGZyYWN0aW9uYWwgZnJhbWUgcmF0ZSBtb2RlLAo+Pj4gKyAqLwo+Pj4gKyNkZWZpbmUgVjRM Ml9DSURfWElMSU5YX1NESVJYX1NFQVJDSF9NT0RFUwo+PiAJKFY0TDJfQ0lEX1hJTElOWF9TRElS WCArIDQpCj4+PiArLyoKPj4+ICsgKiBHZXQgRGV0ZWN0ZWQgTW9kZSBjb250cm9sCj4+PiArICoK Pj4+ICsgKiBDb250cm9sIFZhbHVlIC0gTW9kZSBkZXRlY3RlZAo+Pj4gKyAqICAgICAgICAwICAg ICAgLSAgICAgU0QKPj4+ICsgKiAgICAgICAgMSAgICAgIC0gICAgIEhECj4+PiArICogICAgICAg IDIgICAgICAtICAgICAzRyAoM0dBICYgM0dCKQo+Pj4gKyAqICAgICAgICAzICAgICAgLSAgICAg NkcKPj4+ICsgKiAgICAgICAgNCAgICAgIC0gICAgIDEyRyBpbnRlZ2VyIGZyYW1lIHJhdGUKPj4+ ICsgKiAgICAgICAgNSAgICAgIC0gICAgIDEyRyBmcmFjdGlvbmFsIGZyYW1lIHJhdGUKPj4+ICsg Ki8KPj4+ICsjZGVmaW5lIFY0TDJfQ0lEX1hJTElOWF9TRElSWF9NT0RFX0RFVEVDVAo+PiAJKFY0 TDJfQ0lEX1hJTElOWF9TRElSWCArIDUpCj4+PiArLyogR2V0IG51bWJlciBvZiBDUkMgZXJyb3Jz IHN0YXR1cyBjb250cm9sICovCj4+PiArI2RlZmluZSBWNEwyX0NJRF9YSUxJTlhfU0RJUlhfQ1JD Cj4+IAkoVjRMMl9DSURfWElMSU5YX1NESVJYICsgNikKPj4+ICsvKiBHZXQgRURIIGVycm9yIGNv dW50IGNvbnRyb2wgKi8KPj4+ICsjZGVmaW5lIFY0TDJfQ0lEX1hJTElOWF9TRElSWF9FREhfRVJS Q05UCj4+IAkoVjRMMl9DSURfWElMSU5YX1NESVJYICsgNykKPj4+ICsvKiBHZXQgRURIIHN0YXR1 cyBjb250cm9sICovCj4+PiArI2RlZmluZSBWNEwyX0NJRF9YSUxJTlhfU0RJUlhfRURIX1NUQVRV Uwo+PiAJKFY0TDJfQ0lEX1hJTElOWF9TRElSWCArIDgpCj4+PiArLyogR2V0IFRyYW5zcG9ydCBJ bnRlcmxhY2VkIHN0YXR1cyB3aGV0aGVyIGl0IGlzIGludGVybGFjZWQgb3Igbm90ICovCj4+PiAr I2RlZmluZSBWNEwyX0NJRF9YSUxJTlhfU0RJUlhfVFNfSVNfSU5URVJMQUNFRAo+PiAJKFY0TDJf Q0lEX1hJTElOWF9TRElSWCArIDkpCj4+PiArLyogR2V0IG51bWJlciBvZiBBY3RpdmUgU3RyZWFt cyAqLwo+Pj4gKyNkZWZpbmUgVjRMMl9DSURfWElMSU5YX1NESVJYX0FDVElWRV9TVFJFQU1TCj4+ IAkoVjRMMl9DSURfWElMSU5YX1NESVJYICsgMTApCj4+PiArLyoKPj4+ICsgKiBHZXQgaWYgdGhl IGRldGVjdGVkIG1vZGUgaXMgM0dCLgo+Pj4gKyAqIENhbiBiZSB1c2VkIHRvIGRpc3Rpbmd1aXNo ZWQgYmV0d2VlbiAzR0EgYW5kIDNHQgo+Pj4gKyAqLwo+Pj4gKyNkZWZpbmUgVjRMMl9DSURfWElM SU5YX1NESVJYX0lTXzNHQgo+PiAJKFY0TDJfQ0lEX1hJTElOWF9TRElSWCArIDExKQo+Pj4gKwo+ Pj4gICNlbmRpZiAvKiBfX1VBUElfWElMSU5YX1Y0TDJfQ09OVFJPTFNfSF9fICovCj4+Pgo+Pgo+ PiBSZWdhcmRzLAo+Pgo+PiAJSGFucwo+IAo+IFJlZ2FyZHMKPiBWaXNoYWwgU2FnYXIKPiAKCgpf X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1hcm0t a2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmcK aHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1hcm0ta2Vy bmVsCg==