get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.0/patches/2218797/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2218797,
    "url": "http://patchwork.ozlabs.org/api/1.0/patches/2218797/?format=api",
    "project": {
        "id": 22,
        "url": "http://patchwork.ozlabs.org/api/1.0/projects/22/?format=api",
        "name": "HostAP Development",
        "link_name": "hostap",
        "list_id": "hostap.lists.infradead.org",
        "list_email": "hostap@lists.infradead.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20260401220220.4418-9-andrei.otcheretianski@intel.com>",
    "date": "2026-04-01T22:01:17",
    "name": "[08/71] wpa_supplicant: Support NAN local schedule configuration",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "64b50144fd9eb8b4b51e4f3dd4df31e90b5cdc0e",
    "submitter": {
        "id": 62065,
        "url": "http://patchwork.ozlabs.org/api/1.0/people/62065/?format=api",
        "name": "Andrei Otcheretianski",
        "email": "andrei.otcheretianski@intel.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/hostap/patch/20260401220220.4418-9-andrei.otcheretianski@intel.com/mbox/",
    "series": [
        {
            "id": 498402,
            "url": "http://patchwork.ozlabs.org/api/1.0/series/498402/?format=api",
            "date": "2026-04-01T22:01:09",
            "name": "NAN Data Path and Bootstrapping support",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/498402/mbox/"
        }
    ],
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2218797/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "\n <hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n secure) header.d=lists.infradead.org header.i=@lists.infradead.org\n header.a=rsa-sha256 header.s=bombadil.20210309 header.b=fc36aq03;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256\n header.s=Intel header.b=e82wMSW4;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=none (no SPF record) smtp.mailfrom=lists.infradead.org\n (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org;\n envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from bombadil.infradead.org (bombadil.infradead.org\n [IPv6:2607:7c80:54:3::133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fmJw44lZXz1yGY\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 02 Apr 2026 09:05:56 +1100 (AEDT)",
            "from localhost ([::1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1w83gl-0000000G9kH-2wsH;\n\tWed, 01 Apr 2026 22:05:27 +0000",
            "from mgamail.intel.com ([198.175.65.20])\n\tby bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1w83gi-0000000G9ga-1G84\n\tfor hostap@lists.infradead.org;\n\tWed, 01 Apr 2026 22:05:25 +0000",
            "from fmviesa003.fm.intel.com ([10.60.135.143])\n  by orvoesa112.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 01 Apr 2026 15:05:23 -0700",
            "from iapp347.iil.intel.com (HELO 87c02287900a.iil.intel.com)\n ([10.167.28.6])\n  by fmviesa003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 01 Apr 2026 15:05:22 -0700"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20210309; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:\n\tMessage-ID:Date:Subject:To:From:Reply-To:Cc:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=NE6SvrsuyZy9vJJCooy3JF7jXTGz9GsPhgS7o697QV0=; b=fc36aq03gba/Cm\n\tbL1iqH4/ogwVsjGYoDVw+W6nD8SfmMA3Hk5ASmiFGMRvB87ChJGf6anDHMyxnO945hRY8R64UuMWg\n\tNuWCold/KoyfHx8ed4QLSt4ip7gPZK97izlF3+95m8x4XD2yUQKu9UUVIZyNwLs8o0R2MbXDBvWeX\n\t1/wWctxrZL7JfPCNlIOeAzts5CyyqabfXw/PFICUsEu+X2l98MdsbB/qw29813vh/kUpeBbmZrAif\n\ty7DSos8aDPRV/ICFMdUppjSxx/h8eKsr6N0mnWa7pe/dkSMSDmz1lDs+R29JrZa52xoZaZshGuZ7y\n\tUO7xLdjSPN7dXXNosATg==;",
            "v=1; a=rsa-sha256; c=relaxed/simple;\n  d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n  t=1775081124; x=1806617124;\n  h=from:to:subject:date:message-id:in-reply-to:references:\n   mime-version:content-transfer-encoding;\n  bh=OryyQoMEGBvLI4O5gp9MutQVX6576Bz4aZrnld3ESQc=;\n  b=e82wMSW4gpH2SeZOaTWTYHCOAtA2ByXGtYCG3UWu7+5zIVCNexJQX7Gs\n   rcKqNhd2EA4u/TOqIYd/snhcSZGhJkrOyxQROxXyNVoONMNo1SKcUOz67\n   2zCbAwIV0GI3XEZOzPk6wzbejlqMuuokvUe00kLO7MsQDLwBuSqp+B93K\n   FVgvEBObp6rIEIYXnM9F6i8uX9JWtfSkL8IkznzC/1cUmITFIjrcAJCeo\n   6YD7+oBMidoZcNQYLPvVesoCxgSqeD163Ie46AGl/rJEOC/4xbjAGZiQ7\n   TKADnrzEZKHJnamxz7pXIZ7L03a3z4GOfTZo/MgARFBWW62ctWzKNMgg0\n   w==;"
        ],
        "X-CSE-ConnectionGUID": [
            "th7DfR60TXmvGEqlMhjV3Q==",
            "YDxjDHa3SVKtzS6izPOIow=="
        ],
        "X-CSE-MsgGUID": [
            "aQu6kP8JSi+zDrRxWN4FbQ==",
            "Z3XbHcEcTluaLI7Id0pqAQ=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6800,10657,11746\"; a=\"75851581\"",
            "E=Sophos;i=\"6.23,153,1770624000\";\n   d=\"scan'208\";a=\"75851581\""
        ],
        "X-ExtLoop1": "1",
        "From": "Andrei Otcheretianski <andrei.otcheretianski@intel.com>",
        "To": "hostap@lists.infradead.org",
        "Subject": "[PATCH 08/71] wpa_supplicant: Support NAN local schedule\n configuration",
        "Date": "Thu,  2 Apr 2026 01:01:17 +0300",
        "Message-ID": "<20260401220220.4418-9-andrei.otcheretianski@intel.com>",
        "X-Mailer": "git-send-email 2.53.0",
        "In-Reply-To": "<20260401220220.4418-1-andrei.otcheretianski@intel.com>",
        "References": "<20260401220220.4418-1-andrei.otcheretianski@intel.com>",
        "MIME-Version": "1.0",
        "X-CRM114-Version": "20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ",
        "X-CRM114-CacheID": "sfid-20260401_150524_454194_CBC415DF ",
        "X-CRM114-Status": "GOOD (  24.07  )",
        "X-Spam-Score": "-1.9 (-)",
        "X-Spam-Report": "Spam detection software,\n running on the system \"bombadil.infradead.org\",\n has NOT identified this incoming email as spam.  The original\n message has been attached to this so you can view it or label\n similar future email.  If you have any questions, see\n the administrator of that system for details.\n Content preview:  Add a control interface API to configure local NAN\n schedule.\n    Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> ---\n    wpa_supplicant/ctrl_iface.c | 3 + wpa_supplicant/driver_i.h | 9 +\n wpa_supplicant/nan_supplicant.c\n    | 436 +++++++++++++++++++++ [...]\n Content analysis details:   (-1.9 points, 5.0 required)\n  pts rule name              description\n ---- ----------------------\n --------------------------------------------------\n -2.3 RCVD_IN_DNSWL_MED      RBL: Sender listed at https://www.dnswl.org/,\n                             medium trust\n                             [198.175.65.20 listed in list.dnswl.org]\n  1.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to\n                              Validity was blocked.  See\n                             https://knowledge.validity.com/hc/en-us/articles/20961730681243\n                              for more information.\n                             [198.175.65.20 listed in\n bl.score.senderscore.com]\n  1.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The\n                             query to Validity was blocked.  See\n                             https://knowledge.validity.com/hc/en-us/articles/20961730681243\n                              for more information.\n                          [198.175.65.20 listed in\n sa-trusted.bondedsender.org]\n  1.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to\n                              Validity was blocked.  See\n                             https://knowledge.validity.com/hc/en-us/articles/20961730681243\n                              for more information.\n                             [198.175.65.20 listed in sa-accredit.habeas.com]\n  0.0 SPF_HELO_NONE          SPF: HELO does not publish an SPF Record\n -0.0 SPF_PASS               SPF: sender matches SPF record\n  0.1 DKIM_SIGNED            Message has a DKIM or DK signature,\n not necessarily valid\n -0.1 DKIM_VALID_EF          Message has a valid DKIM or DK signature from\n                             envelope-from domain\n -0.1 DKIM_VALID_AU          Message has a valid DKIM or DK signature from\n author's\n                             domain\n -0.1 DKIM_VALID             Message has at least one valid DKIM or DK\n signature\n -1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%\n                             [score: 0.0000]\n -0.5 DKIMWL_WL_HIGH         DKIMwl.org - High trust sender",
        "X-BeenThere": "hostap@lists.infradead.org",
        "X-Mailman-Version": "2.1.34",
        "Precedence": "list",
        "List-Id": "<hostap.lists.infradead.org>",
        "List-Unsubscribe": "<http://lists.infradead.org/mailman/options/hostap>,\n <mailto:hostap-request@lists.infradead.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.infradead.org/pipermail/hostap/>",
        "List-Post": "<mailto:hostap@lists.infradead.org>",
        "List-Help": "<mailto:hostap-request@lists.infradead.org?subject=help>",
        "List-Subscribe": "<http://lists.infradead.org/mailman/listinfo/hostap>,\n <mailto:hostap-request@lists.infradead.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Sender": "\"Hostap\" <hostap-bounces@lists.infradead.org>",
        "Errors-To": "hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org"
    },
    "content": "Add a control interface API to configure local NAN schedule.\n\nSigned-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>\n---\n wpa_supplicant/ctrl_iface.c       |   3 +\n wpa_supplicant/driver_i.h         |   9 +\n wpa_supplicant/nan_supplicant.c   | 436 ++++++++++++++++++++++++++++++\n wpa_supplicant/nan_supplicant.h   |   1 +\n wpa_supplicant/wpa_supplicant_i.h |   3 +\n 5 files changed, 452 insertions(+)",
    "diff": "diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c\nindex d095402c1c..aa42514509 100644\n--- a/wpa_supplicant/ctrl_iface.c\n+++ b/wpa_supplicant/ctrl_iface.c\n@@ -14395,6 +14395,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,\n \t} else if (os_strncmp(buf, \"NAN_UPDATE_CONF\", 15) == 0) {\n \t\tif (wpas_nan_update_conf(wpa_s) < 0)\n \t\t\treply_len = -1;\n+\t} else if (os_strncmp(buf, \"NAN_SCHED_CONFIG_MAP \", 21) == 0) {\n+\t\tif (wpas_nan_sched_config_map(wpa_s, buf + 21) < 0)\n+\t\t\treply_len = -1;\n #endif /* CONFIG_NAN */\n \t} else {\n \t\tos_memcpy(reply, \"UNKNOWN COMMAND\\n\", 16);\ndiff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h\nindex 60eb31ca10..4d67145955 100644\n--- a/wpa_supplicant/driver_i.h\n+++ b/wpa_supplicant/driver_i.h\n@@ -1304,6 +1304,15 @@ wpa_drv_nan_update_config(struct wpa_supplicant *wpa_s,\n \treturn wpa_s->driver->nan_change_config(wpa_s->drv_priv, conf);\n }\n \n+static inline int wpa_drv_nan_config_schedule(struct wpa_supplicant *wpa_s,\n+\t\t\t\t\t      u8 map_id,\n+\t\t\t\t\t      struct nan_schedule_config *conf)\n+{\n+\tif (!wpa_s->driver->nan_config_schedule)\n+\t\treturn -1;\n+\treturn wpa_s->driver->nan_config_schedule(wpa_s->drv_priv, map_id,\n+\t\t\t\t\t\t  conf);\n+}\n #endif /* CONFIG_NAN */\n \n #endif /* DRIVER_I_H */\ndiff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c\nindex 2706b45afd..3027af79c9 100644\n--- a/wpa_supplicant/nan_supplicant.c\n+++ b/wpa_supplicant/nan_supplicant.c\n@@ -22,6 +22,8 @@\n #include \"p2p_supplicant.h\"\n #include \"pr_supplicant.h\"\n #include \"nan_supplicant.h\"\n+#include \"common/ieee802_11_common.h\"\n+#include \"bitfield.h\"\n \n #define DEFAULT_NAN_MASTER_PREF 2\n #define DEFAULT_NAN_DUAL_BAND   0\n@@ -38,6 +40,89 @@\n \n #ifdef CONFIG_NAN\n \n+static int get_center(u8 channel, const u8 *center_channels, size_t num_chan,\n+\t\t      int width)\n+{\n+\tint span = (width - 20) / 10;\n+\tsize_t i;\n+\n+\tfor (i = 0; i < num_chan; i++) {\n+\t\tif (channel >= center_channels[i] - span &&\n+\t\t    channel <= center_channels[i] + span)\n+\t\t\treturn center_channels[i];\n+\t}\n+\n+\treturn 0;\n+}\n+\n+\n+static bool wpas_nan_valid_chan(struct wpa_supplicant *wpa_s,\n+\t\t\t\tenum hostapd_hw_mode mode,\n+\t\t\t        u8 channel, int bw, u8 op_class,\n+\t\t\t\tu8 *cf1)\n+{\n+\tstatic const u8 nan_160mhz_5ghz_chans[] = { 50, 114, 163 };\n+\tstatic const u8 nan_80mhz_5ghz_chans[] =\n+\t\t{ 42, 58, 106, 122, 138, 155, 171 };\n+\n+\tstruct hostapd_hw_modes *hw_mode;\n+\tint width, span;\n+\tu8 c, center = 0;\n+\n+\thw_mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, mode, false);\n+\tif (!hw_mode)\n+\t\treturn false;\n+\n+\tswitch (bw) {\n+\t\tcase BW20:\n+\t\t\twidth = 20;\n+\t\t\tcenter = channel;\n+\t\t\tbreak;\n+\t\tcase BW40PLUS:\n+\t\tcase BW40MINUS:\n+\t\t\twidth = 40;\n+\t\t\tcenter = bw == BW40PLUS ? channel + 2 : channel - 2;\n+\t\t\tbreak;\n+\t\tcase BW80:\n+\t\t\twidth = 80;\n+\t\t\tcenter = get_center(channel, nan_80mhz_5ghz_chans,\n+\t\t\t\t\t    ARRAY_SIZE(nan_80mhz_5ghz_chans),\n+\t\t\t\t\t    width);\n+\t\t\tbreak;\n+\t\tcase BW160:\n+\t\t\twidth = 160;\n+\t\t\tcenter = get_center(channel, nan_160mhz_5ghz_chans,\n+\t\t\t\t\t    ARRAY_SIZE(nan_160mhz_5ghz_chans),\n+\t\t\t\t\t    width);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn false;\n+\t}\n+\n+\tif (!center)\n+\t\treturn false;\n+\n+\tspan = (width - 20) / 10;\n+\tfor (c = center - span; c <= center + span; c += 4) {\n+\t\tint freq = ieee80211_chan_to_freq(NULL, op_class, c);\n+\n+\t\tif (freq < 0)\n+\t\t\treturn false;\n+\n+\t\tif (ieee80211_is_dfs(freq, wpa_s->hw.modes,\n+\t\t\t\t     wpa_s->hw.num_modes))\n+\t\t\treturn false;\n+\t}\n+\n+\t/* Wide channels use center */\n+\tif (width > 40)\n+\t\tchannel = center;\n+\n+\t*cf1 = center;\n+\treturn verify_channel(hw_mode, op_class, channel, bw) == ALLOWED;\n+}\n+\n+\n static int wpas_nan_start_cb(void *ctx, const struct nan_cluster_config *config)\n {\n \tstruct wpa_supplicant *wpa_s = ctx;\n@@ -55,9 +140,28 @@ static int wpas_nan_update_config_cb(void *ctx,\n }\n \n \n+static void clear_sched_config(struct nan_schedule_config *sched_cfg)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < sched_cfg->num_channels; i++)\n+\t\twpabuf_free(sched_cfg->channels[i].time_bitmap);\n+\n+\tos_memset(sched_cfg, 0, sizeof(*sched_cfg));\n+}\n+\n+\n static void wpas_nan_stop_cb(void *ctx)\n {\n \tstruct wpa_supplicant *wpa_s = ctx;\n+\tint i;\n+\n+\tfor (i = 0; i < MAX_NAN_RADIOS; i++) {\n+\t\tif (wpa_s->nan_sched[i].num_channels) {\n+\t\t\twpa_drv_nan_config_schedule(wpa_s, i + 1, NULL);\n+\t\t\tclear_sched_config(&wpa_s->nan_sched[i]);\n+\t\t}\n+\t}\n \n \twpa_drv_nan_stop(wpa_s);\n }\n@@ -144,9 +248,14 @@ int wpas_nan_init(struct wpa_supplicant *wpa_s)\n \n void wpas_nan_deinit(struct wpa_supplicant *wpa_s)\n {\n+\tint i;\n+\n \tif (!wpa_s || !wpa_s->nan)\n \t\treturn;\n \n+\tfor (i = 0; i < MAX_NAN_RADIOS; i++)\n+\t\tclear_sched_config(&wpa_s->nan_sched[i]);\n+\n \tnan_deinit(wpa_s->nan);\n \twpa_s->nan = NULL;\n }\n@@ -283,6 +392,333 @@ int wpas_nan_update_conf(struct wpa_supplicant *wpa_s)\n }\n \n \n+static u8 nan_select_40mhz_channel(u8 chan, u8 *op_class, int *bw)\n+{\n+\tint op;\n+\n+\tfor (op = 0; global_op_class[op].op_class; op++) {\n+\t\tconst struct oper_class_map *o = &global_op_class[op];\n+\t\tint c;\n+\n+\t\t/* No support for 40 Mhz on 2.4 GHz */\n+\t\tif (o->mode != HOSTAPD_MODE_IEEE80211A)\n+\t\t\tcontinue;\n+\n+\t\t/* Currenlty don't support NAN for 80+, 6 GHz etc. */\n+\t\tif (o->op_class > 129)\n+\t\t\tcontinue;\n+\n+\t\tif (o->bw != BW40MINUS && o->bw != BW40PLUS)\n+\t\t\tcontinue;\n+\n+\t\tfor (c = o->min_chan; c <= o->max_chan; c += o->inc) {\n+\t\t\tif (c != chan)\n+\t\t\t\tcontinue;\n+\n+\t\t\t*op_class = o->op_class;\n+\t\t\t*bw = o->bw;\n+\t\t\tif (o->bw == BW40MINUS)\n+\t\t\t\treturn chan - 2;\n+\t\t\telse\n+\t\t\t\treturn chan + 2;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+\n+static int wpas_nan_select_channel_params(struct wpa_supplicant *wpa_s,\n+\t\t\t\t\t  int freq, int *center_freq1,\n+\t\t\t\t\t  int *center_freq2, int *bandwidth)\n+{\n+\tu8 chan, op_class, center;\n+\tenum hostapd_hw_mode mode;\n+\tint bw;\n+\n+\tmode = ieee80211_freq_to_channel_ext(freq, 0,\n+\t\t\t\t\t     CONF_OPER_CHWIDTH_USE_HT,\n+\t\t\t\t\t     &op_class, &chan);\n+\tif (mode == NUM_HOSTAPD_MODES) {\n+\t\twpa_printf(MSG_DEBUG,\n+\t\t\t  \"NAN: Invalid frequency %d\", freq);\n+\t\treturn -1;\n+\t}\n+\n+\tif (!wpas_nan_valid_chan(wpa_s, mode, chan, BW20, op_class, &center)) {\n+\t\twpa_printf(MSG_DEBUG,\n+\t\t\t   \"NAN: Channel not valid for NAN (freq = %d)\",\n+\t\t\t   freq);\n+\t\treturn -1;\n+\t}\n+\n+\t/* On 2.4 GHz use 20 MHz channels */\n+\tif (freq >= 2412 && freq <= 2484)\n+\t\tgoto out;\n+\n+\t/* TODO: Add support for NAN on other bands */\n+\tif (freq < 5180 || freq > 5885) {\n+\t\twpa_printf(MSG_DEBUG,\n+\t\t\t   \"NAN: Unsupported frequency %d\", freq);\n+\t\treturn -1;\n+\t}\n+\n+\tif (wpas_nan_valid_chan(wpa_s, mode, chan, BW160, 129, &center)) {\n+\t\t*center_freq1 = ieee80211_chan_to_freq(NULL, op_class, center);\n+\t\t*center_freq2 = 0;\n+\t\t*bandwidth = 160;\n+\t\treturn 0;\n+\t}\n+\n+\tif (wpas_nan_valid_chan(wpa_s, mode, chan, BW80, 128, &center)) {\n+\t\t*center_freq1 = ieee80211_chan_to_freq(NULL, op_class, center);\n+\t\t*center_freq2 = 0;\n+\t\t*bandwidth = 80;\n+\t\treturn 0;\n+\t}\n+\n+\tif (nan_select_40mhz_channel(chan, &op_class, &bw) &&\n+\t\twpas_nan_valid_chan(wpa_s, mode, center, bw, op_class, &center)) {\n+\t\t*center_freq1 = ieee80211_chan_to_freq(NULL, op_class,\n+\t\t\t\t\t\t       center);\n+\t\t*center_freq2 = 0;\n+\t\t*bandwidth = 40;\n+\t\treturn 0;\n+\t}\n+\n+out:\n+\t/* Fallback to 20 MHz */\n+\t*center_freq1 = freq;\n+\t*center_freq2 = 0;\n+\t*bandwidth = 20;\n+\treturn 0;\n+}\n+\n+\n+static void nan_dump_sched_config(const char *title,\n+\t\t\t\t  struct nan_schedule_config *sched_cfg)\n+{\n+\tint i;\n+\n+\twpa_printf(MSG_DEBUG, \"%s: num_channels=%d\", title,\n+\t\t   sched_cfg->num_channels);\n+\tfor (i = 0; i < sched_cfg->num_channels; i++) {\n+\t\twpa_printf(MSG_DEBUG,\n+\t\t\t   \"  Channel %d: freq=%d center_freq1=%d center_freq2=%d bandwidth=%d time_bitmap_len=%zu\",\n+\t\t\t   i + 1,\n+\t\t\t   sched_cfg->channels[i].freq,\n+\t\t\t   sched_cfg->channels[i].center_freq1,\n+\t\t\t   sched_cfg->channels[i].center_freq2,\n+\t\t\t   sched_cfg->channels[i].bandwidth,\n+\t\t\t   wpabuf_len(sched_cfg->channels[i].time_bitmap));\n+\t}\n+}\n+\n+\n+/* Parse format NAN_SCHED_CONFIG_MAP map_id=<id> [freq:bitmap_hex]..\n+   If no bitmaps provided - clear the map */\n+int wpas_nan_sched_config_map(struct wpa_supplicant *wpa_s, const char *cmd)\n+{\n+\tstruct nan_schedule_config sched_cfg;\n+\tchar *token, *context = NULL;\n+\tu8 map_id;\n+\tchar *pos;\n+\tint *shared_freqs;\n+\tint shared_freqs_count, unused_freqs_count, ret = -1;\n+\tstruct bitfield *bf_total;\n+\tint expected_bitmap_len;\n+\n+\tif (!wpas_nan_ready(wpa_s))\n+\t\treturn -1;\n+\n+\tif (os_strncmp(cmd, \"map_id=\", 7) != 0) {\n+\t\twpa_printf(MSG_DEBUG, \"NAN: Invalid schedule map format\");\n+\t\treturn -1;\n+\t}\n+\n+\tmap_id = atoi(cmd + 7);\n+\n+\tif (!map_id || map_id >= MAX_NAN_RADIOS) {\n+\t\twpa_printf(MSG_DEBUG, \"NAN: Invalid map_id %d\", map_id);\n+\t\treturn -1;\n+\t}\n+\n+\tif (map_id > wpa_s->nan_capa.num_radios) {\n+\t\twpa_printf(MSG_DEBUG,\n+\t\t\t   \"NAN: map_id %d exceeds number of supported NAN radios %d\",\n+\t\t\t   map_id, wpa_s->nan_capa.num_radios);\n+\t\treturn -1;\n+\t}\n+\n+\tif (!wpa_s->nan_capa.schedule_period ||\n+\t    !wpa_s->nan_capa.slot_duration) {\n+\t\t    wpa_printf(MSG_DEBUG,\n+\t\t\t       \"NAN: Driver doesn't advertise support for NAN scheduling\");\n+\t\t    return -1;\n+\t}\n+\n+\texpected_bitmap_len =(wpa_s->nan_capa.schedule_period /\n+\t\t\t      wpa_s->nan_capa.slot_duration + 7) / 8;\n+\n+\tos_memset(&sched_cfg, 0, sizeof(sched_cfg));\n+\n+\tpos = os_strchr(cmd + 7, ' ');\n+\tif (!pos) {\n+\t\tclear_sched_config(&wpa_s->nan_sched[map_id - 1]);\n+\t\twpa_printf(MSG_DEBUG,\n+\t\t\t   \"NAN: Missing freq:timebitmap pairs - cleanup schedule\");\n+\t\treturn wpa_drv_nan_config_schedule(wpa_s, map_id, &sched_cfg);;\n+\t}\n+\n+\tshared_freqs = os_calloc(wpa_s->num_multichan_concurrent,\n+\t\t\t\t sizeof(int));\n+\tif (!shared_freqs) {\n+\t\twpa_printf(MSG_DEBUG,\n+\t\t\t  \"NAN: Failed to allocate memory for shared freqs\");\n+\t\treturn -1;\n+\t}\n+\n+\tshared_freqs_count =\n+\t\tget_shared_radio_freqs(wpa_s, shared_freqs,\n+\t\t\t\t       wpa_s->num_multichan_concurrent,\n+\t\t\t\t       false);\n+\n+\tunused_freqs_count = wpa_s->nan_capa.sched_chans - shared_freqs_count;\n+\n+\tbf_total = bitfield_alloc(wpa_s->nan_capa.schedule_period /\n+\t\t\t\t  wpa_s->nan_capa.slot_duration);\n+\tif (!bf_total) {\n+\t\twpa_printf(MSG_DEBUG,\n+\t\t\t  \"NAN: Failed to allocate bitfield for total schedule\");\n+\t\tgoto out;\n+\t}\n+\n+\t/* Parse freq:timebitmap pairs */\n+\tpos++;\n+\twhile ((token = str_token(pos, \" \", &context))) {\n+\t\tint j, i = sched_cfg.num_channels;;\n+\t\tstruct bitfield *bf_chan = NULL;\n+\t\tchar *colon = os_strchr(token, ':');\n+\n+\t\tif (i >= wpa_s->nan_capa.sched_chans) {\n+\t\t\twpa_printf(MSG_DEBUG,\n+\t\t\t\t   \"NAN: Exceeded max channels per radio %u\",\n+\t\t\t\t   wpa_s->nan_capa.sched_chans);\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tif (!colon) {\n+\t\t\twpa_printf(MSG_DEBUG,\n+\t\t\t\t   \"NAN: Invalid freq:timebitmap format\");\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tsched_cfg.channels[i].freq = atoi(token);\n+\t\tif (sched_cfg.channels[i].freq <= 0) {\n+\t\t\twpa_printf(MSG_DEBUG, \"NAN: Invalid frequency %d\",\n+\t\t\t\t   sched_cfg.channels[i].freq);\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tfor (j = 0; j < i; j++) {\n+\t\t\tif (sched_cfg.channels[j].freq ==\n+\t\t\t    sched_cfg.channels[i].freq) {\n+\t\t\t\twpa_printf(MSG_DEBUG,\n+\t\t\t\t\t   \"NAN: Duplicate frequency %d\",\n+\t\t\t\t\t   sched_cfg.channels[i].freq);\n+\t\t\t\tgoto out;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (wpas_nan_select_channel_params(wpa_s, sched_cfg.channels[i].freq,\n+\t\t\t\t\t\t   &sched_cfg.channels[i].center_freq1,\n+\t\t\t\t\t\t   &sched_cfg.channels[i].center_freq2,\n+\t\t\t\t\t\t   &sched_cfg.channels[i].bandwidth)) {\n+\t\t\twpa_printf(MSG_DEBUG,\n+\t\t\t\t   \"NAN: Failed to select channel params for freq %d\",\n+\t\t\t\t   sched_cfg.channels[i].freq);\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tif (!int_array_includes(shared_freqs,\n+\t\t\t\t        sched_cfg.channels[i].freq)) {\n+\t\t\tif (!unused_freqs_count) {\n+\t\t\t\twpa_printf(MSG_DEBUG,\n+\t\t\t\t\t   \"NAN: No unused radio frequency available for freq %d\",\n+\t\t\t\t\t   sched_cfg.channels[i].freq);\n+\t\t\t\tgoto out;\n+\t\t\t}\n+\n+\t\t\tunused_freqs_count--;\n+\t\t}\n+\n+\t\tsched_cfg.channels[i].time_bitmap = wpabuf_parse_bin(colon + 1);\n+\t\tif (!sched_cfg.channels[i].time_bitmap) {\n+\t\t\twpa_printf(MSG_DEBUG, \"NAN: Invalid time bitmap\");\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tsched_cfg.num_channels++;\n+\n+\t\tif ((int)wpabuf_len(sched_cfg.channels[i].time_bitmap) !=\n+\t\t    expected_bitmap_len) {\n+\t\t\twpa_printf(MSG_DEBUG,\n+\t\t\t\t   \"NAN: Invalid bitmap length (%zu) for period=%d, slot length=%d\",\n+\t\t\t\t   wpabuf_len(sched_cfg.channels[i].time_bitmap),\n+\t\t\t\t   wpa_s->nan_capa.schedule_period,\n+\t\t\t\t   wpa_s->nan_capa.slot_duration);\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tbf_chan = bitfield_alloc_data(\n+\t\t\twpabuf_head(sched_cfg.channels[i].time_bitmap),\n+\t\t\twpabuf_len(sched_cfg.channels[i].time_bitmap));\n+\t\tif (!bf_chan) {\n+\t\t\twpa_printf(MSG_DEBUG,\n+\t\t\t\t   \"NAN: Failed to allocate bitfield for channel schedule\");\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tif (bitfield_intersects(bf_total, bf_chan)) {\n+\t\t\twpa_printf(MSG_DEBUG,\n+\t\t\t\t   \"NAN: Overlapping time bitmap detected for freq %d\",\n+\t\t\t\t   sched_cfg.channels[i].freq);\n+\t\t\tbitfield_free(bf_chan);\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\t/* Extract RX NSS from upper nibble of num_antennas */\n+\t\tsched_cfg.channels[i].rx_nss =\n+\t\t\t(wpa_s->nan_capa.num_antennas >> 4) & 0x0f;\n+\n+\t\tbitfield_union_in_place(bf_total, bf_chan);\n+\t\tbitfield_free(bf_chan);\n+\t}\n+\n+\tnan_dump_sched_config(\"NAN: Set schedule config\", &sched_cfg);\n+\tret = wpa_drv_nan_config_schedule(wpa_s, map_id, &sched_cfg);\n+\tif (ret < 0) {\n+\t\twpa_printf(MSG_DEBUG,\n+\t\t\t   \"NAN: Failed to configure NAN schedule map_id %d\",\n+\t\t\t   map_id);\n+\t\tgoto out;\n+\t}\n+\n+\t/* Store the configured schedule */\n+\twpa_s->schedule_sequence_id++;\n+\tclear_sched_config(&wpa_s->nan_sched[map_id - 1]);\n+\tos_memcpy(&wpa_s->nan_sched[map_id - 1], &sched_cfg,\n+\t\t  sizeof(sched_cfg));\n+out:\n+\tos_free(bf_total);\n+\tos_free(shared_freqs);\n+\tif (ret)\n+\t\tclear_sched_config(&sched_cfg);\n+\n+\treturn ret;\n+}\n+\n+\n void wpas_nan_cluster_join(struct wpa_supplicant *wpa_s,\n \t\t\t   const u8 *cluster_id,\n \t\t\t   bool new_cluster)\ndiff --git a/wpa_supplicant/nan_supplicant.h b/wpa_supplicant/nan_supplicant.h\nindex 242a3b632a..f7502e3ec8 100644\n--- a/wpa_supplicant/nan_supplicant.h\n+++ b/wpa_supplicant/nan_supplicant.h\n@@ -24,6 +24,7 @@ void wpas_nan_cluster_join(struct wpa_supplicant *wpa_s,\n \t\t\t   const u8 *cluster_id,\n \t\t\t   bool new_cluster);\n void wpas_nan_next_dw(struct wpa_supplicant *wpa_s, u32 freq);\n+int wpas_nan_sched_config_map(struct wpa_supplicant *wpa_s, const char *cmd);\n \n #else /* CONFIG_NAN */\n \ndiff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h\nindex a4b88a5a96..7737e9d4c8 100644\n--- a/wpa_supplicant/wpa_supplicant_i.h\n+++ b/wpa_supplicant/wpa_supplicant_i.h\n@@ -1722,9 +1722,12 @@ struct wpa_supplicant {\n \tbool nan_mgmt;\n \n #ifdef CONFIG_NAN\n+#define MAX_NAN_RADIOS 2\n \tstruct nan_capa nan_capa;\n \tstruct nan_data *nan;\n \tstruct nan_cluster_config nan_config;\n+\tu8 schedule_sequence_id;\n+\tstruct nan_schedule_config nan_sched[MAX_NAN_RADIOS];\n #endif /* CONFIG_NAN */\n #ifdef CONFIG_ENC_ASSOC\n \tbool assoc_resp_encrypted; /* Whether (Re)Association Response frame\n",
    "prefixes": [
        "08/71"
    ]
}