]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
PR: Process EDCA Capability Attribute from USD PR element
authorPeddolla Harshavardhan Reddy <peddolla@qti.qualcomm.com>
Sat, 26 Apr 2025 19:49:59 +0000 (01:19 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 17 Oct 2025 10:22:51 +0000 (13:22 +0300)
Parse part of Proximity Ranging element corresponding to the Proximity
Ranging EDCA Capability Attribute and store the corresponding data in a
structure. This attribute contains capabilities that tell if the device
can act as an EDCA based ranging initiator, EDCA based ranging
responder, and a list of channels on which the device supports EDCA
based ranging and other device specific capabilities.

Signed-off-by: Peddolla Harshavardhan Reddy <peddolla@qti.qualcomm.com>
src/common/proximity_ranging.c
src/common/proximity_ranging.h

index 9e734224e4369033bbab10d4795e9d73eb49f8d9..6664c32ef5ea7e7c0826128a9ff0b8aff83dfbb7 100644 (file)
 #include "proximity_ranging.h"
 
 
+static bool valid_country_ch(char c)
+{
+       return c >= 'A' && c <= 'Z';
+}
+
+
 static void pr_device_free(struct pr_data *pr, struct pr_device *dev)
 {
        os_free(dev);
@@ -714,6 +720,59 @@ static int pr_parse_elements(const u8 *data, size_t len, struct pr_message *msg)
 }
 
 
+static int pr_process_channels(const u8 *channel_list, size_t channel_list_len,
+                              struct pr_channels *ch)
+{
+       u8 channels;
+       const u8 *pos, *end;
+       u8 op_class_count;
+
+       if (channel_list_len < 1)
+               return -1;
+
+       pos = channel_list;
+       end = channel_list + channel_list_len;
+
+       /* Number of Channel Entries */
+       /* Get total count of the operational classes */
+       op_class_count = pos[0];
+       wpa_printf(MSG_DEBUG, "PR: Total operational classes: %u",
+                  op_class_count);
+       pos++;
+
+       /* Channel Entry List */
+       ch->op_classes = 0;
+       while (end - pos > 2 && (ch->op_classes <= op_class_count)) {
+               struct pr_op_class *cl = &ch->op_class[ch->op_classes];
+
+               cl->op_class = *pos++; /* Operating Class */
+               channels = *pos++; /* Number of Channels */
+
+               /* Channel List */
+               if (channels > end - pos) {
+                       wpa_printf(MSG_INFO,
+                                  "PR: Invalid channel list channel %d, size: %ld",
+                                  channels, end - pos);
+                       return -1;
+               }
+               cl->channels = channels > PR_MAX_OP_CLASS_CHANNELS ?
+                       PR_MAX_OP_CLASS_CHANNELS : channels;
+               os_memcpy(cl->channel, pos, cl->channels);
+               pos += channels;
+               ch->op_classes++;
+       }
+
+       if (ch->op_classes != op_class_count) {
+               wpa_printf(MSG_INFO,
+                          "PR: Channel list count mismatch %lu != %d",
+                          ch->op_classes, op_class_count);
+               return -1;
+       }
+
+       return 0;
+}
+
+
 static void pr_process_ranging_capabilities(const u8 *caps, size_t caps_len,
                                            struct pr_capabilities *pr_caps)
 {
@@ -758,6 +817,45 @@ static void pr_process_ranging_capabilities(const u8 *caps, size_t caps_len,
 }
 
 
+static void pr_process_edca_capabilities(const u8 *caps, size_t caps_len,
+                                        struct edca_capabilities *edca_caps)
+{
+       const u8 *pos, *end;
+
+       if (caps_len < 7)
+               return;
+
+       pos = caps;
+       end = caps + caps_len;
+
+       /* Ranging Role */
+       if (*pos & PR_ISTA_SUPPORT)
+               edca_caps->ista_support = true;
+       if (*pos & PR_RSTA_SUPPORT)
+               edca_caps->rsta_support = true;
+       pos++;
+
+       /* Ranging Parameters */
+       edca_caps->edca_hw_caps = WPA_GET_LE16(pos);
+       pos += 2;
+
+       /* Country String */
+       os_memcpy(edca_caps->country, pos, 3);
+       pos += 3;
+
+       pr_process_channels(pos, end - pos, &edca_caps->channels);
+
+       wpa_printf(MSG_DEBUG,
+                  "PR: EDCA ISTA support=%u, EDCA RSTA support=%u, op classes count=%lu, country=%c%c",
+                  edca_caps->ista_support, edca_caps->rsta_support,
+                  edca_caps->channels.op_classes,
+                  valid_country_ch(edca_caps->country[0]) ?
+                  edca_caps->country[0] : '_',
+                  valid_country_ch(edca_caps->country[1]) ?
+                  edca_caps->country[1] : '_');
+}
+
+
 void pr_process_usd_elems(struct pr_data *pr, const u8 *ies, u16 ies_len,
                          const u8 *peer_addr, unsigned int freq)
 {
@@ -795,5 +893,10 @@ void pr_process_usd_elems(struct pr_data *pr, const u8 *ies, u16 ies_len,
        pr_process_ranging_capabilities(msg.pr_capability,
                                        msg.pr_capability_len, &dev->pr_caps);
 
+       if (dev->pr_caps.edca_support && msg.edca_capability)
+               pr_process_edca_capabilities(msg.edca_capability,
+                                            msg.edca_capability_len,
+                                            &dev->edca_caps);
+
        pr_parse_free(&msg);
 }
index cc7fea3d5e7c9e3c03b901112068131d3a12b929..12bf90d9fd037a6ce89335f5ebb41dcfaf28f5fc 100644 (file)
@@ -249,6 +249,7 @@ struct pr_device {
        u8 pr_device_addr[ETH_ALEN];
 
        struct pr_capabilities pr_caps;
+       struct edca_capabilities edca_caps;
 
        /* Password to be used in PASN-SAE by the Seeker.
         * This is updated with valid password if DIRA matches for the peer.