• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "p2plink_channel_freq.h"
17 
18 #include <errno.h>
19 #include <stdlib.h>
20 #include <time.h>
21 
22 #include "securec.h"
23 #include "softbus_adapter_mem.h"
24 #include "softbus_errcode.h"
25 #include "softbus_log.h"
26 
27 #define MAX_CHANNEL_ITEM 165
28 #define INVALID_5G_CHANNEL 165
29 
30 #define FREQUENCY_2G_FIRST 2412
31 #define FREQUENCY_2G_LAST 2472
32 #define FREQUENCY_5G_FIRST 5170
33 #define FREQUENCY_5G_LAST 5825
34 #define CHANNEL_2G_FIRST 1
35 #define CHANNEL_2G_LAST 13
36 #define CHANNEL_5G_FIRST 34
37 #define CHANNEL_5G_LAST 165
38 #define FREQUENCY_STEP 5
39 #define CHANNEL_INVALID (-1)
40 #define FREQUENCY_INVALID (-1)
41 
P2plinkChannelListToString(const P2pLink5GList * channelList,char * channelString,int32_t len)42 int32_t P2plinkChannelListToString(const P2pLink5GList *channelList, char *channelString, int32_t len)
43 {
44     if ((channelList == NULL) || (channelList->num == 0)) {
45         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_DBG, "channelList is null.");
46         return SOFTBUS_OK;
47     }
48 
49     if (channelString == NULL) {
50         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:invalid param.", __func__);
51         return SOFTBUS_INVALID_PARAM;
52     }
53 
54     int32_t ret = sprintf_s(channelString, len, "%d", channelList->chans[0]);
55     if (ret == -1) {
56         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "sprintf_s failed, errno = %d.", errno);
57         return SOFTBUS_MEM_ERR;
58     }
59 
60     for (int32_t i = 1; i < channelList->num; i++) {
61         int32_t writeRet = sprintf_s(channelString + ret, len - ret, "##%d", channelList->chans[i]);
62         if (writeRet == -1) {
63             SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "sprintf_s failed, errno = %d.", errno);
64             return SOFTBUS_MEM_ERR;
65         }
66         ret += writeRet;
67     }
68 
69     return SOFTBUS_OK;
70 }
71 
P2pLinkParseItemDataByDelimit(char * srcStr,const char * delimit,char * list[],int32_t num,int32_t * outNum)72 void P2pLinkParseItemDataByDelimit(char *srcStr, const char *delimit, char *list[], int32_t num, int32_t *outNum)
73 {
74     // srcStr will be cut.
75     if (srcStr == NULL || delimit == NULL || list == NULL || outNum == NULL || num == 0) {
76         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:invalid param.", __func__);
77         return;
78     }
79 
80     char *itemStr = NULL;
81     char *saveItemPtr = NULL;
82     itemStr = strtok_s(srcStr, delimit, &saveItemPtr);
83     int32_t index = 0;
84     while (itemStr != NULL) {
85         if (index >= num) {
86             SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_DBG, "over max input num, index = %d, max num = %d.", index, num);
87             index++;
88             break;
89         }
90         list[index++] = itemStr;
91         itemStr = strtok_s(NULL, delimit, &saveItemPtr);
92     }
93 
94     *outNum = index;
95 }
96 
97 // The caller needs to free memory
StringToChannelList(const char * channelString)98 static P2pLink5GList *StringToChannelList(const char *channelString)
99 {
100     if (channelString == NULL || strlen(channelString) == 0) {
101         return NULL;
102     }
103 
104     char *list[MAX_CHANNEL_ITEM] = {0};
105     int32_t num;
106     char channelStringClone[CHAN_LIST_LEN] = {0};
107     if (strcpy_s(channelStringClone, sizeof(channelStringClone), channelString) != EOK) {
108         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "strcpy_s failed, errno = %d.", errno);
109         return NULL;
110     }
111     P2pLinkParseItemDataByDelimit(channelStringClone, "##", list, MAX_CHANNEL_ITEM, &num);
112     if (num == 0) {
113         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "parse channel string failed.");
114         return NULL;
115     }
116 
117     P2pLink5GList *channelList = SoftBusCalloc(sizeof(P2pLink5GList) + sizeof(int32_t) * num);
118     if (channelList == NULL) {
119         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "calloc failed.");
120         return NULL;
121     }
122 
123     channelList->num = num;
124     for (int32_t i = 0; i < num; i++) {
125         channelList->chans[i] = atoi(list[i]);
126     }
127 
128     return channelList;
129 }
130 
GetChannelByFreq(int32_t freq)131 static int32_t GetChannelByFreq(int32_t freq)
132 {
133     if (freq >= FREQUENCY_2G_FIRST && freq <= FREQUENCY_2G_LAST) {
134         return ((freq - FREQUENCY_2G_FIRST) / FREQUENCY_STEP) + CHANNEL_2G_FIRST;
135     } else if (freq >= FREQUENCY_5G_FIRST && freq <= FREQUENCY_5G_LAST) {
136         return ((freq - FREQUENCY_5G_FIRST) / FREQUENCY_STEP) + CHANNEL_5G_FIRST;
137     } else {
138         return CHANNEL_INVALID;
139     }
140 }
141 
Is2GBand(int32_t freq)142 static bool Is2GBand(int32_t freq)
143 {
144     if (freq >= FREQUENCY_2G_FIRST && freq <= FREQUENCY_2G_LAST) {
145         return true;
146     }
147     return false;
148 }
149 
IsInChannelList(int32_t channelItem,const P2pLink5GList * channelList)150 static bool IsInChannelList(int32_t channelItem, const P2pLink5GList *channelList)
151 {
152     if (channelList == NULL || channelList->num == 0) {
153         return false;
154     }
155 
156     for (int32_t i = 0; i < channelList->num; i++) {
157         if (channelItem == channelList->chans[i]) {
158             return true;
159         }
160     }
161 
162     return false;
163 }
164 
P2pLinkUpateAndGetStationFreq(const P2pLink5GList * channelList)165 int32_t P2pLinkUpateAndGetStationFreq(const P2pLink5GList *channelList)
166 {
167     int32_t freq = P2pLinkGetFrequency();
168     if (freq < FREQUENCY_2G_FIRST) {
169         return FREQUENCY_INVALID;
170     }
171     int32_t channel = GetChannelByFreq(freq);
172     if (freq > FREQUENCY_2G_LAST && !IsInChannelList(channel, channelList)) {
173         freq = FREQUENCY_INVALID;
174     }
175 
176     return freq;
177 }
178 
GetFreqByChannel(int32_t channel)179 static int32_t GetFreqByChannel(int32_t channel)
180 {
181     if (channel >= CHANNEL_2G_FIRST && channel <= CHANNEL_2G_LAST) {
182         return (channel - CHANNEL_2G_FIRST) * FREQUENCY_STEP + FREQUENCY_2G_FIRST;
183     } else if (channel >= CHANNEL_5G_FIRST && channel <= CHANNEL_5G_LAST) {
184         return (channel - CHANNEL_5G_FIRST) * FREQUENCY_STEP + FREQUENCY_5G_FIRST;
185     }
186     SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "channel to freq, channel = %d.", channel);
187     return FREQUENCY_INVALID;
188 }
189 
GenerateFrequency(const P2pLink5GList * channelList,const P2pLink5GList * gcChannelList,const P2pLink5GList * gcScoreList)190 static int32_t GenerateFrequency(const P2pLink5GList *channelList, const P2pLink5GList *gcChannelList,
191     const P2pLink5GList *gcScoreList)
192 {
193     (void)gcScoreList;
194     if (channelList == NULL || channelList->num <= 0) {
195         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_DBG, "local 5g channel list is null.");
196         return FREQUENCY_INVALID;
197     }
198 
199     P2pLink5GList *result = (P2pLink5GList *)SoftBusCalloc(sizeof(P2pLink5GList) + sizeof(int32_t) * channelList->num);
200     if (result == NULL) {
201         return FREQUENCY_INVALID;
202     }
203     result->num = 0;
204     for (int32_t i = 0; i < channelList->num; i++) {
205         if (channelList->chans[i] == INVALID_5G_CHANNEL) {
206             SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_DBG, "can not use 5g channel 165.");
207             continue;
208         }
209         if (IsInChannelList(channelList->chans[i], gcChannelList)) {
210             result->chans[result->num] = channelList->chans[i];
211             result->num++;
212         }
213     }
214     if (result->num == 0) {
215         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_DBG, "can not use 5G channel.");
216         SoftBusFree(result);
217         return FREQUENCY_INVALID;
218     }
219     int32_t bestFreq = GetFreqByChannel(result->chans[0]);
220     // not suppot local channel scores, so don't caculate local channel and peer channel scores
221     SoftBusFree(result);
222     return bestFreq;
223 }
224 
ChoseChannel5gFreq(const GcInfo * gc,const P2pLink5GList * channelList,const P2pLink5GList * gcChannelList,int32_t localStationFreq,int32_t gcStationFreq)225 static int32_t ChoseChannel5gFreq(const GcInfo *gc, const P2pLink5GList *channelList,
226     const P2pLink5GList *gcChannelList, int32_t localStationFreq, int32_t gcStationFreq)
227 {
228     if (gcChannelList != NULL || channelList != NULL) {
229         int32_t localChannel = GetChannelByFreq(localStationFreq);
230         if (IsInChannelList(localChannel, channelList) && IsInChannelList(localChannel, gcChannelList)) {
231             return localStationFreq;
232         }
233 
234         int32_t gcChannel = GetChannelByFreq(gcStationFreq);
235         if (IsInChannelList(gcChannel, channelList) && IsInChannelList(gcChannel, gcChannelList)) {
236             return gcStationFreq;
237         }
238 
239         /* channel score will be supported soon. */
240         int32_t freq = GenerateFrequency(channelList, gcChannelList, NULL);
241         if (freq != FREQUENCY_INVALID) {
242             return freq;
243         }
244         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_DBG, "no suitable 5G frequency");
245     }
246     return FREQUENCY_INVALID;
247 }
248 
P2plinkGetGroupGrequency(const GcInfo * gc,const P2pLink5GList * channelList)249 int32_t P2plinkGetGroupGrequency(const GcInfo *gc, const P2pLink5GList *channelList)
250 {
251     if (gc == NULL) {
252         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:invalid param.", __func__);
253         return SOFTBUS_INVALID_PARAM;
254     }
255 
256     int32_t localStationFreq = P2pLinkUpateAndGetStationFreq(channelList);
257     int32_t gcStationFreq = gc->stationFrequency;
258 
259     SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_INFO, "local station freq = %d, gc station greq = %d.",
260         localStationFreq, gcStationFreq);
261     if (localStationFreq != -1 || gcStationFreq != -1) {
262         int32_t recommandFreq;
263         int32_t ret = P2pLinkGetRecommendChannel(&recommandFreq);
264         if (ret == SOFTBUS_OK) {
265             SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_DBG, "get p2p recommand success, freq = %d.", recommandFreq);
266             return recommandFreq;
267         }
268     }
269 
270     P2pLink5GList *gcChannelList = StringToChannelList(gc->channelList);
271     int32_t channel5gFreq = ChoseChannel5gFreq(gc, channelList, gcChannelList, localStationFreq, gcStationFreq);
272     SoftBusFree(gcChannelList);
273     if (channel5gFreq != -1) {
274         return channel5gFreq;
275     }
276 
277     if (Is2GBand(localStationFreq)) {
278         return localStationFreq;
279     }
280 
281     if (Is2GBand(gcStationFreq)) {
282         return gcStationFreq;
283     }
284 
285     return FREQUENCY_2G_FIRST;
286 }