P2P: Fix the calculation of group common freqs
[mech_eap.git] / src / p2p / p2p_utils.c
index 615cce4..2e2aa8a 100644 (file)
@@ -9,6 +9,8 @@
 #include "includes.h"
 
 #include "common.h"
+#include "common/defs.h"
+#include "common/ieee802_11_common.h"
 #include "p2p_i.h"
 
 
@@ -54,56 +56,7 @@ int p2p_random(char *buf, size_t len)
  */
 int p2p_channel_to_freq(int op_class, int channel)
 {
-       /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
-       /* TODO: more operating classes */
-       switch (op_class) {
-       case 81:
-               /* channels 1..13 */
-               if (channel < 1 || channel > 13)
-                       return -1;
-               return 2407 + 5 * channel;
-       case 82:
-               /* channel 14 */
-               if (channel != 14)
-                       return -1;
-               return 2414 + 5 * channel;
-       case 83: /* channels 1..9; 40 MHz */
-       case 84: /* channels 5..13; 40 MHz */
-               if (channel < 1 || channel > 13)
-                       return -1;
-               return 2407 + 5 * channel;
-       case 115: /* channels 36,40,44,48; indoor only */
-       case 118: /* channels 52,56,60,64; dfs */
-               if (channel < 36 || channel > 64)
-                       return -1;
-               return 5000 + 5 * channel;
-       case 124: /* channels 149,153,157,161 */
-       case 125: /* channels 149,153,157,161,165,169 */
-               if (channel < 149 || channel > 161)
-                       return -1;
-               return 5000 + 5 * channel;
-       case 116: /* channels 36,44; 40 MHz; indoor only */
-       case 117: /* channels 40,48; 40 MHz; indoor only */
-       case 119: /* channels 52,60; 40 MHz; dfs */
-       case 120: /* channels 56,64; 40 MHz; dfs */
-               if (channel < 36 || channel > 64)
-                       return -1;
-               return 5000 + 5 * channel;
-       case 126: /* channels 149,157; 40 MHz */
-       case 127: /* channels 153,161; 40 MHz */
-               if (channel < 149 || channel > 161)
-                       return -1;
-               return 5000 + 5 * channel;
-       case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
-               if (channel < 36 || channel > 161)
-                       return -1;
-               return 5000 + 5 * channel;
-       case 180: /* 60 GHz band, channels 1..4 */
-               if (channel < 1 || channel > 4)
-                       return -1;
-               return 56160 + 2160 * channel;
-       }
-       return -1;
+       return ieee80211_chan_to_freq(NULL, op_class, channel);
 }
 
 
@@ -115,50 +68,11 @@ int p2p_channel_to_freq(int op_class, int channel)
  */
 int p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel)
 {
-       /* TODO: more operating classes */
-       if (freq >= 2412 && freq <= 2472) {
-               if ((freq - 2407) % 5)
-                       return -1;
-
-               *op_class = 81; /* 2.407 GHz, channels 1..13 */
-               *channel = (freq - 2407) / 5;
-               return 0;
-       }
-
-       if (freq == 2484) {
-               *op_class = 82; /* channel 14 */
-               *channel = 14;
-               return 0;
-       }
-
-       if (freq >= 5180 && freq <= 5240) {
-               if ((freq - 5000) % 5)
-                       return -1;
-
-               *op_class = 115; /* 5 GHz, channels 36..48 */
-               *channel = (freq - 5000) / 5;
-               return 0;
-       }
-
-       if (freq >= 5745 && freq <= 5805) {
-               if ((freq - 5000) % 5)
-                       return -1;
-
-               *op_class = 124; /* 5 GHz, channels 149..161 */
-               *channel = (freq - 5000) / 5;
-               return 0;
-       }
-
-       if (freq >= 58320 && freq <= 64800) {
-               if ((freq - 58320) % 2160)
-                       return -1;
-
-               *op_class = 180; /* 60 GHz, channels 1..4 */
-               *channel = (freq - 56160) / 2160;
-               return 0;
-       }
+       if (ieee80211_freq_to_channel_ext(freq, 0, 0, op_class, channel) ==
+           NUM_HOSTAPD_MODES)
+               return -1;
 
-       return -1;
+       return 0;
 }
 
 
@@ -241,20 +155,15 @@ static void p2p_op_class_union(struct p2p_reg_class *cl,
 
 
 /**
- * p2p_channels_union - Union of channel lists
- * @a: First set of channels
+ * p2p_channels_union_inplace - Inplace union of channel lists
+ * @res: Input data and place for returning union of the channel sets
  * @b: Second set of channels
- * @res: Data structure for returning the union of channels
  */
-void p2p_channels_union(const struct p2p_channels *a,
-                       const struct p2p_channels *b,
-                       struct p2p_channels *res)
+void p2p_channels_union_inplace(struct p2p_channels *res,
+                               const struct p2p_channels *b)
 {
        size_t i, j;
 
-       if (a != res)
-               os_memcpy(res, a, sizeof(*res));
-
        for (i = 0; i < res->reg_classes; i++) {
                struct p2p_reg_class *cl = &res->reg_class[i];
                for (j = 0; j < b->reg_classes; j++) {
@@ -284,6 +193,21 @@ void p2p_channels_union(const struct p2p_channels *a,
 }
 
 
+/**
+ * p2p_channels_union - Union of channel lists
+ * @a: First set of channels
+ * @b: Second set of channels
+ * @res: Data structure for returning the union of channels
+ */
+void p2p_channels_union(const struct p2p_channels *a,
+                       const struct p2p_channels *b,
+                       struct p2p_channels *res)
+{
+       os_memcpy(res, a, sizeof(*res));
+       p2p_channels_union_inplace(res, b);
+}
+
+
 void p2p_channels_remove_freqs(struct p2p_channels *chan,
                               const struct wpa_freq_range_list *list)
 {
@@ -428,7 +352,7 @@ void p2p_channels_dump(struct p2p_data *p2p, const char *title,
                const struct p2p_reg_class *c;
                c = &chan->reg_class[i];
                ret = os_snprintf(pos, end - pos, " %u:", c->reg_class);
-               if (ret < 0 || ret >= end - pos)
+               if (os_snprintf_error(end - pos, ret))
                        break;
                pos += ret;
 
@@ -436,7 +360,7 @@ void p2p_channels_dump(struct p2p_data *p2p, const char *title,
                        ret = os_snprintf(pos, end - pos, "%s%u",
                                          j == 0 ? "" : ",",
                                          c->channel[j]);
-                       if (ret < 0 || ret >= end - pos)
+                       if (os_snprintf_error(end - pos, ret))
                                break;
                        pos += ret;
                }
@@ -535,12 +459,22 @@ int p2p_channels_to_freqs(const struct p2p_channels *channels, int *freq_list,
                        break;
                for (j = 0; j < c->channels; j++) {
                        int freq;
+                       unsigned int k;
+
                        if (idx + 1 == max_len)
                                break;
                        freq = p2p_channel_to_freq(c->reg_class,
                                                   c->channel[j]);
                        if (freq < 0)
                                continue;
+
+                       for (k = 0; k < idx; k++) {
+                               if (freq_list[k] == freq)
+                                       break;
+                       }
+
+                       if (k < idx)
+                               continue;
                        freq_list[idx++] = freq;
                }
        }