18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * P2P - generic helper functions 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009, Atheros Communications 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 12fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt#include "common/ieee802_11_common.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_random - Generate random string for SSID and passphrase 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for returning the result 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Number of octets to write to the buffer 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function generates a random string using the following character set: 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 'A'-'Z', 'a'-'z', '0'-'9'. 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_random(char *buf, size_t len) 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 val; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 letters = 'Z' - 'A' + 1; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 numbers = 10; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_get_random((unsigned char *) buf, len)) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Character set: 'A'-'Z', 'a'-'z', '0'-'9' */ 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < len; i++) { 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = buf[i]; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val %= 2 * letters + numbers; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (val < letters) 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[i] = 'A' + val; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (val < 2 * letters) 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[i] = 'a' + (val - letters); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[i] = '0' + (val - 2 * letters); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 504b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt/** 514b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt * p2p_channel_to_freq - Convert channel info to frequency 524b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt * @op_class: Operating class 534b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt * @channel: Channel number 544b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt * Returns: Frequency in MHz or -1 if the specified channel is unknown 554b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt */ 564b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidtint p2p_channel_to_freq(int op_class, int channel) 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 58fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return ieee80211_chan_to_freq(NULL, op_class, channel); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_freq_to_channel - Convert frequency into channel info 644b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt * @op_class: Buffer for returning operating class 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @channel: Buffer for returning channel number 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 if the specified frequency is unknown 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 684b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidtint p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel) 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: more operating classes */ 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (freq >= 2412 && freq <= 2472) { 72b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if ((freq - 2407) % 5) 73b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return -1; 74b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 754b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt *op_class = 81; /* 2.407 GHz, channels 1..13 */ 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *channel = (freq - 2407) / 5; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (freq == 2484) { 814b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt *op_class = 82; /* channel 14 */ 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *channel = 14; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (freq >= 5180 && freq <= 5240) { 87b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if ((freq - 5000) % 5) 88b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return -1; 89b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 904b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt *op_class = 115; /* 5 GHz, channels 36..48 */ 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *channel = (freq - 5000) / 5; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (freq >= 5745 && freq <= 5805) { 96b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if ((freq - 5000) % 5) 97b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return -1; 98b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 994b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt *op_class = 124; /* 5 GHz, channels 149..161 */ 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *channel = (freq - 5000) / 5; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 104a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt if (freq >= 5745 && freq <= 5845) { 105a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt if ((freq - 5000) % 5) 106a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt return -1; 107a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt 108a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt *op_class = 125; /* 5 GHz, channels 149..169 */ 109a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt *channel = (freq - 5000) / 5; 110a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt return 0; 111a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt } 112a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt 113661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (freq >= 58320 && freq <= 64800) { 114661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if ((freq - 58320) % 2160) 115661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return -1; 116661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 117661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt *op_class = 180; /* 60 GHz, channels 1..4 */ 118661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt *channel = (freq - 56160) / 2160; 119661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return 0; 120661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 121661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_reg_class_intersect(const struct p2p_reg_class *a, 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct p2p_reg_class *b, 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_reg_class *res) 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i, j; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->reg_class = a->reg_class; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < a->channels; i++) { 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (j = 0; j < b->channels; j++) { 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a->channel[i] != b->channel[j]) 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->channel[res->channels] = a->channel[i]; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->channels++; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res->channels == P2P_MAX_REG_CLASS_CHANNELS) 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_channels_intersect - Intersection of supported channel lists 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @a: First set of supported channels 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @b: Second set of supported channels 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @res: Data structure for returning the intersection of support channels 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to find a common set of supported channels. Both 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * input channels sets are assumed to use the same country code. If different 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * country codes are used, the regulatory class numbers may not be matched 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * correctly and results are undefined. 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_channels_intersect(const struct p2p_channels *a, 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct p2p_channels *b, 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct p2p_channels *res) 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i, j; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(res, 0, sizeof(*res)); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < a->reg_classes; i++) { 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct p2p_reg_class *a_reg = &a->reg_class[i]; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (j = 0; j < b->reg_classes; j++) { 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct p2p_reg_class *b_reg = &b->reg_class[j]; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a_reg->reg_class != b_reg->reg_class) 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_reg_class_intersect( 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt a_reg, b_reg, 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &res->reg_class[res->reg_classes]); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res->reg_class[res->reg_classes].channels) { 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->reg_classes++; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res->reg_classes == P2P_MAX_REG_CLASSES) 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtstatic void p2p_op_class_union(struct p2p_reg_class *cl, 18668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt const struct p2p_reg_class *b_cl) 18768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{ 18868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt size_t i, j; 18968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 19068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt for (i = 0; i < b_cl->channels; i++) { 19168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt for (j = 0; j < cl->channels; j++) { 19268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (b_cl->channel[i] == cl->channel[j]) 19368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt break; 19468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 19568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (j == cl->channels) { 19668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (cl->channels == P2P_MAX_REG_CLASS_CHANNELS) 19768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return; 19868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt cl->channel[cl->channels++] = b_cl->channel[i]; 19968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 20068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 20168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt} 20268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 20368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 20468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt/** 205fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * p2p_channels_union_inplace - Inplace union of channel lists 206fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * @res: Input data and place for returning union of the channel sets 20768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt * @b: Second set of channels 20868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt */ 209fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidtvoid p2p_channels_union_inplace(struct p2p_channels *res, 210fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt const struct p2p_channels *b) 21168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{ 21268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt size_t i, j; 21368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 21468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt for (i = 0; i < res->reg_classes; i++) { 21568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt struct p2p_reg_class *cl = &res->reg_class[i]; 21668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt for (j = 0; j < b->reg_classes; j++) { 21768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt const struct p2p_reg_class *b_cl = &b->reg_class[j]; 21868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (cl->reg_class != b_cl->reg_class) 21968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt continue; 22068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt p2p_op_class_union(cl, b_cl); 22168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 22268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 22368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 22468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt for (j = 0; j < b->reg_classes; j++) { 22568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt const struct p2p_reg_class *b_cl = &b->reg_class[j]; 22668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 22768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt for (i = 0; i < res->reg_classes; i++) { 22868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt struct p2p_reg_class *cl = &res->reg_class[i]; 22968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (cl->reg_class == b_cl->reg_class) 23068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt break; 23168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 23268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 23368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (i == res->reg_classes) { 23468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (res->reg_classes == P2P_MAX_REG_CLASSES) 23568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return; 23668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt os_memcpy(&res->reg_class[res->reg_classes++], 23768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt b_cl, sizeof(struct p2p_reg_class)); 23868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 23968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 24068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt} 24168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 24268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 243fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt/** 244fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * p2p_channels_union - Union of channel lists 245fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * @a: First set of channels 246fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * @b: Second set of channels 247fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * @res: Data structure for returning the union of channels 248fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt */ 249fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidtvoid p2p_channels_union(const struct p2p_channels *a, 250fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt const struct p2p_channels *b, 251fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt struct p2p_channels *res) 252fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt{ 253fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt os_memcpy(res, a, sizeof(*res)); 254fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt p2p_channels_union_inplace(res, b); 255fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt} 256fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 257fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 25868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtvoid p2p_channels_remove_freqs(struct p2p_channels *chan, 25968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt const struct wpa_freq_range_list *list) 26068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{ 26168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt size_t o, c; 26268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 26368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (list == NULL) 26468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return; 26568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 26668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt o = 0; 26768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt while (o < chan->reg_classes) { 26868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt struct p2p_reg_class *op = &chan->reg_class[o]; 26968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 27068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt c = 0; 27168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt while (c < op->channels) { 27268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt int freq = p2p_channel_to_freq(op->reg_class, 27368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt op->channel[c]); 27468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (freq > 0 && freq_range_list_includes(list, freq)) { 27568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt op->channels--; 27668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt os_memmove(&op->channel[c], 27768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt &op->channel[c + 1], 27868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt op->channels - c); 27968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } else 28068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt c++; 28168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 28268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 28368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (op->channels == 0) { 28468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt chan->reg_classes--; 28568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt os_memmove(&chan->reg_class[o], &chan->reg_class[o + 1], 28668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt (chan->reg_classes - o) * 28768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt sizeof(struct p2p_reg_class)); 28868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } else 28968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt o++; 29068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 29168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt} 29268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 29368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * p2p_channels_includes - Check whether a channel is included in the list 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @channels: List of supported channels 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reg_class: Regulatory class of the channel to search 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @channel: Channel number of the channel to search 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if channel was found or 0 if not 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_channels_includes(const struct p2p_channels *channels, u8 reg_class, 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 channel) 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i, j; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < channels->reg_classes; i++) { 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct p2p_reg_class *reg = &channels->reg_class[i]; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reg->reg_class != reg_class) 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (j = 0; j < reg->channels; j++) { 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reg->channel[j] == channel) 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3187a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidtint p2p_channels_includes_freq(const struct p2p_channels *channels, 3197a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt unsigned int freq) 3207a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt{ 3217a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt size_t i, j; 3227a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt for (i = 0; i < channels->reg_classes; i++) { 3237a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt const struct p2p_reg_class *reg = &channels->reg_class[i]; 3247a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt for (j = 0; j < reg->channels; j++) { 3254b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (p2p_channel_to_freq(reg->reg_class, 3264b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt reg->channel[j]) == (int) freq) 3277a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt return 1; 3287a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt } 3297a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt } 3307a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt return 0; 3317a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt} 3327a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt 3337a5e50a0554bee77a9da492ea3d86f46147f1671Dmitry Shmidt 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_supported_freq(struct p2p_data *p2p, unsigned int freq) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 op_reg_class, op_channel; 3374b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (p2p_freq_to_channel(freq, &op_reg_class, &op_channel) < 0) 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return p2p_channels_includes(&p2p->cfg->channels, op_reg_class, 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_channel); 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 34244c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt 34344c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt 34468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtint p2p_supported_freq_go(struct p2p_data *p2p, unsigned int freq) 34568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{ 34668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt u8 op_reg_class, op_channel; 34768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (p2p_freq_to_channel(freq, &op_reg_class, &op_channel) < 0) 34868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return 0; 34968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return p2p_channels_includes(&p2p->cfg->channels, op_reg_class, 35068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt op_channel) && 35168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt !freq_range_list_includes(&p2p->no_go_freq, freq); 35268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt} 35368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 35468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 35568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtint p2p_supported_freq_cli(struct p2p_data *p2p, unsigned int freq) 35668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{ 35768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt u8 op_reg_class, op_channel; 35868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (p2p_freq_to_channel(freq, &op_reg_class, &op_channel) < 0) 35968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return 0; 36068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return p2p_channels_includes(&p2p->cfg->channels, op_reg_class, 36168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt op_channel) || 36268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt p2p_channels_includes(&p2p->cfg->cli_channels, op_reg_class, 36368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt op_channel); 36468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt} 36568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 36668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 36744c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidtunsigned int p2p_get_pref_freq(struct p2p_data *p2p, 36844c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt const struct p2p_channels *channels) 36944c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt{ 37044c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt unsigned int i; 37143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt int freq = 0; 37243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt const struct p2p_channels *tmpc = channels ? 37343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt channels : &p2p->cfg->channels; 37443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt 37543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (tmpc == NULL) 37643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt return 0; 37744c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt 37844c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt for (i = 0; p2p->cfg->pref_chan && i < p2p->cfg->num_pref_chan; i++) { 37944c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt freq = p2p_channel_to_freq(p2p->cfg->pref_chan[i].op_class, 38044c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt p2p->cfg->pref_chan[i].chan); 38143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (p2p_channels_includes_freq(tmpc, freq)) 38244c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt return freq; 38344c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt } 38444c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt return 0; 38544c957860ca714a86357591f39aff0bfa904c743Dmitry Shmidt} 3864ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 3874ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 3884ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidtvoid p2p_channels_dump(struct p2p_data *p2p, const char *title, 3894ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt const struct p2p_channels *chan) 3904ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt{ 3914ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt char buf[500], *pos, *end; 3924ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt size_t i, j; 3934ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt int ret; 3944ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 3954ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt pos = buf; 3964ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt end = pos + sizeof(buf); 3974ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 3984ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt for (i = 0; i < chan->reg_classes; i++) { 3994ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt const struct p2p_reg_class *c; 4004ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt c = &chan->reg_class[i]; 4014ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt ret = os_snprintf(pos, end - pos, " %u:", c->reg_class); 402fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (os_snprintf_error(end - pos, ret)) 4034ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt break; 4044ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt pos += ret; 4054ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 4064ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt for (j = 0; j < c->channels; j++) { 4074ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt ret = os_snprintf(pos, end - pos, "%s%u", 4084ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt j == 0 ? "" : ",", 4094ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt c->channel[j]); 410fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (os_snprintf_error(end - pos, ret)) 4114ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt break; 4124ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt pos += ret; 4134ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt } 4144ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt } 4154ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt *pos = '\0'; 4164ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 4174ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt p2p_dbg(p2p, "%s:%s", title, buf); 4184ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt} 419e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 420e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 421d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidtstatic u8 p2p_channel_pick_random(const u8 *channels, unsigned int num_channels) 422d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt{ 423d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt unsigned int r; 424661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (os_get_random((u8 *) &r, sizeof(r)) < 0) 425661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt r = 0; 426d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt r %= num_channels; 427d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt return channels[r]; 428d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt} 429d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt 430d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt 431e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtint p2p_channel_select(struct p2p_channels *chans, const int *classes, 432e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt u8 *op_class, u8 *op_channel) 433e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt{ 434d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt unsigned int i, j; 435e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 436d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt for (j = 0; classes == NULL || classes[j]; j++) { 437a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt for (i = 0; i < chans->reg_classes; i++) { 438a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt struct p2p_reg_class *c = &chans->reg_class[i]; 439e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 440a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt if (c->channels == 0) 441a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt continue; 442e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 443d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt if (classes == NULL || c->reg_class == classes[j]) { 444a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt /* 445a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt * Pick one of the available channels in the 446a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt * operating class at random. 447a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt */ 448a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt *op_class = c->reg_class; 449d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt *op_channel = p2p_channel_pick_random( 450d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt c->channel, c->channels); 451a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt return 0; 452a0d265f81180f341d22511538fa18166e1bbce9fDmitry Shmidt } 453e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt } 454d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt if (classes == NULL) 455d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt break; 456e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt } 457e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 458e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return -1; 459e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt} 460d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt 461d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt 462d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidtint p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class, 463d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt u8 *op_channel) 464d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt{ 465661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt u8 chan[4]; 466d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt unsigned int num_channels = 0; 467d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt 468d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt /* Try to find available social channels from 2.4 GHz */ 469d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt if (p2p_channels_includes(chans, 81, 1)) 470d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt chan[num_channels++] = 1; 471d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt if (p2p_channels_includes(chans, 81, 6)) 472d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt chan[num_channels++] = 6; 473d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt if (p2p_channels_includes(chans, 81, 11)) 474d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt chan[num_channels++] = 11; 475d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt 476661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt /* Try to find available social channels from 60 GHz */ 477661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (p2p_channels_includes(chans, 180, 2)) 478661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt chan[num_channels++] = 2; 479661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 480d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt if (num_channels == 0) 481d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt return -1; 482d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt 483d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt *op_channel = p2p_channel_pick_random(chan, num_channels); 484661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (*op_channel == 2) 485661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt *op_class = 180; 486661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt else 487661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt *op_class = 81; 488d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt 489d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt return 0; 490d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt} 491fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 492fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 493fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidtint p2p_channels_to_freqs(const struct p2p_channels *channels, int *freq_list, 494fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt unsigned int max_len) 495fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt{ 496fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt unsigned int i, idx; 497fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 498fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (!channels || max_len == 0) 499fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return 0; 500fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 501fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt for (i = 0, idx = 0; i < channels->reg_classes; i++) { 502fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt const struct p2p_reg_class *c = &channels->reg_class[i]; 503fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt unsigned int j; 504fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 505fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (idx + 1 == max_len) 506fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt break; 507fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt for (j = 0; j < c->channels; j++) { 508fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt int freq; 509fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (idx + 1 == max_len) 510fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt break; 511fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt freq = p2p_channel_to_freq(c->reg_class, 512fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt c->channel[j]); 513fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (freq < 0) 514fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt continue; 515fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt freq_list[idx++] = freq; 516fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt } 517fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt } 518fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 519fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt freq_list[idx] = 0; 520fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 521fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return idx; 522fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt} 523