2 * P2P - generic helper functions
3 * Copyright (c) 2009, Atheros Communications
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
16 * p2p_random - Generate random string for SSID and passphrase
17 * @buf: Buffer for returning the result
18 * @len: Number of octets to write to the buffer
19 * Returns: 0 on success, -1 on failure
21 * This function generates a random string using the following character set:
22 * 'A'-'Z', 'a'-'z', '0'-'9'.
24 int p2p_random(char *buf
, size_t len
)
28 u8 letters
= 'Z' - 'A' + 1;
31 if (os_get_random((unsigned char *) buf
, len
))
33 /* Character set: 'A'-'Z', 'a'-'z', '0'-'9' */
34 for (i
= 0; i
< len
; i
++) {
36 val
%= 2 * letters
+ numbers
;
39 else if (val
< 2 * letters
)
40 buf
[i
] = 'a' + (val
- letters
);
42 buf
[i
] = '0' + (val
- 2 * letters
);
50 * p2p_channel_to_freq - Convert channel info to frequency
51 * @op_class: Operating class
52 * @channel: Channel number
53 * Returns: Frequency in MHz or -1 if the specified channel is unknown
55 int p2p_channel_to_freq(int op_class
, int channel
)
57 /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
58 /* TODO: more operating classes */
62 if (channel
< 1 || channel
> 13)
64 return 2407 + 5 * channel
;
69 return 2414 + 5 * channel
;
70 case 83: /* channels 1..9; 40 MHz */
71 case 84: /* channels 5..13; 40 MHz */
72 if (channel
< 1 || channel
> 13)
74 return 2407 + 5 * channel
;
75 case 115: /* channels 36,40,44,48; indoor only */
76 case 118: /* channels 52,56,60,64; dfs */
77 if (channel
< 36 || channel
> 64)
79 return 5000 + 5 * channel
;
80 case 124: /* channels 149,153,157,161 */
81 case 125: /* channels 149,153,157,161,165,169 */
82 if (channel
< 149 || channel
> 161)
84 return 5000 + 5 * channel
;
85 case 116: /* channels 36,44; 40 MHz; indoor only */
86 case 117: /* channels 40,48; 40 MHz; indoor only */
87 case 119: /* channels 52,60; 40 MHz; dfs */
88 case 120: /* channels 56,64; 40 MHz; dfs */
89 if (channel
< 36 || channel
> 64)
91 return 5000 + 5 * channel
;
92 case 126: /* channels 149,157; 40 MHz */
93 case 127: /* channels 153,161; 40 MHz */
94 if (channel
< 149 || channel
> 161)
96 return 5000 + 5 * channel
;
103 * p2p_freq_to_channel - Convert frequency into channel info
104 * @op_class: Buffer for returning operating class
105 * @channel: Buffer for returning channel number
106 * Returns: 0 on success, -1 if the specified frequency is unknown
108 int p2p_freq_to_channel(unsigned int freq
, u8
*op_class
, u8
*channel
)
110 /* TODO: more operating classes */
111 if (freq
>= 2412 && freq
<= 2472) {
112 if ((freq
- 2407) % 5)
115 *op_class
= 81; /* 2.407 GHz, channels 1..13 */
116 *channel
= (freq
- 2407) / 5;
121 *op_class
= 82; /* channel 14 */
126 if (freq
>= 5180 && freq
<= 5240) {
127 if ((freq
- 5000) % 5)
130 *op_class
= 115; /* 5 GHz, channels 36..48 */
131 *channel
= (freq
- 5000) / 5;
135 if (freq
>= 5745 && freq
<= 5805) {
136 if ((freq
- 5000) % 5)
139 *op_class
= 124; /* 5 GHz, channels 149..161 */
140 *channel
= (freq
- 5000) / 5;
148 static void p2p_reg_class_intersect(const struct p2p_reg_class
*a
,
149 const struct p2p_reg_class
*b
,
150 struct p2p_reg_class
*res
)
154 res
->reg_class
= a
->reg_class
;
156 for (i
= 0; i
< a
->channels
; i
++) {
157 for (j
= 0; j
< b
->channels
; j
++) {
158 if (a
->channel
[i
] != b
->channel
[j
])
160 res
->channel
[res
->channels
] = a
->channel
[i
];
162 if (res
->channels
== P2P_MAX_REG_CLASS_CHANNELS
)
170 * p2p_channels_intersect - Intersection of supported channel lists
171 * @a: First set of supported channels
172 * @b: Second set of supported channels
173 * @res: Data structure for returning the intersection of support channels
175 * This function can be used to find a common set of supported channels. Both
176 * input channels sets are assumed to use the same country code. If different
177 * country codes are used, the regulatory class numbers may not be matched
178 * correctly and results are undefined.
180 void p2p_channels_intersect(const struct p2p_channels
*a
,
181 const struct p2p_channels
*b
,
182 struct p2p_channels
*res
)
186 os_memset(res
, 0, sizeof(*res
));
188 for (i
= 0; i
< a
->reg_classes
; i
++) {
189 const struct p2p_reg_class
*a_reg
= &a
->reg_class
[i
];
190 for (j
= 0; j
< b
->reg_classes
; j
++) {
191 const struct p2p_reg_class
*b_reg
= &b
->reg_class
[j
];
192 if (a_reg
->reg_class
!= b_reg
->reg_class
)
194 p2p_reg_class_intersect(
196 &res
->reg_class
[res
->reg_classes
]);
197 if (res
->reg_class
[res
->reg_classes
].channels
) {
199 if (res
->reg_classes
== P2P_MAX_REG_CLASSES
)
208 * p2p_channels_includes - Check whether a channel is included in the list
209 * @channels: List of supported channels
210 * @reg_class: Regulatory class of the channel to search
211 * @channel: Channel number of the channel to search
212 * Returns: 1 if channel was found or 0 if not
214 int p2p_channels_includes(const struct p2p_channels
*channels
, u8 reg_class
,
218 for (i
= 0; i
< channels
->reg_classes
; i
++) {
219 const struct p2p_reg_class
*reg
= &channels
->reg_class
[i
];
220 if (reg
->reg_class
!= reg_class
)
222 for (j
= 0; j
< reg
->channels
; j
++) {
223 if (reg
->channel
[j
] == channel
)
231 int p2p_channels_includes_freq(const struct p2p_channels
*channels
,
235 for (i
= 0; i
< channels
->reg_classes
; i
++) {
236 const struct p2p_reg_class
*reg
= &channels
->reg_class
[i
];
237 for (j
= 0; j
< reg
->channels
; j
++) {
238 if (p2p_channel_to_freq(reg
->reg_class
,
239 reg
->channel
[j
]) == (int) freq
)
247 int p2p_supported_freq(struct p2p_data
*p2p
, unsigned int freq
)
249 u8 op_reg_class
, op_channel
;
250 if (p2p_freq_to_channel(freq
, &op_reg_class
, &op_channel
) < 0)
252 return p2p_channels_includes(&p2p
->cfg
->channels
, op_reg_class
,
257 unsigned int p2p_get_pref_freq(struct p2p_data
*p2p
,
258 const struct p2p_channels
*channels
)
263 if (channels
== NULL
) {
264 if (p2p
->cfg
->num_pref_chan
) {
265 freq
= p2p_channel_to_freq(
266 p2p
->cfg
->pref_chan
[0].op_class
,
267 p2p
->cfg
->pref_chan
[0].chan
);
274 for (i
= 0; p2p
->cfg
->pref_chan
&& i
< p2p
->cfg
->num_pref_chan
; i
++) {
275 freq
= p2p_channel_to_freq(p2p
->cfg
->pref_chan
[i
].op_class
,
276 p2p
->cfg
->pref_chan
[i
].chan
);
277 if (p2p_channels_includes_freq(channels
, freq
))
285 void p2p_channels_dump(struct p2p_data
*p2p
, const char *title
,
286 const struct p2p_channels
*chan
)
288 char buf
[500], *pos
, *end
;
293 end
= pos
+ sizeof(buf
);
295 for (i
= 0; i
< chan
->reg_classes
; i
++) {
296 const struct p2p_reg_class
*c
;
297 c
= &chan
->reg_class
[i
];
298 ret
= os_snprintf(pos
, end
- pos
, " %u:", c
->reg_class
);
299 if (ret
< 0 || ret
>= end
- pos
)
303 for (j
= 0; j
< c
->channels
; j
++) {
304 ret
= os_snprintf(pos
, end
- pos
, "%s%u",
307 if (ret
< 0 || ret
>= end
- pos
)
314 p2p_dbg(p2p
, "%s:%s", title
, buf
);