1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <algorithm>
18 #include <cctype>
19 
20 #include "chre/apps/wifi_offload/utility.h"
21 #include "chre/apps/wifi_offload/wifi_offload.h"
22 
23 namespace wifi_offload {
24 namespace utility {
25 namespace {
26 
27 // The length of a string SSID with null-terminator.
28 constexpr size_t kMaxSsidStrLen = CHRE_WIFI_SSID_MAX_LEN + 1;
29 // The length of a formatted BSSID string in XX:XX:XX:XX:XX:XX\0 format.
30 constexpr size_t kBssidStrLen = 18;
31 
ParseSsidToStr(const uint8_t * ssid,size_t ssid_len,char * ssid_str,size_t ssid_str_len)32 bool ParseSsidToStr(const uint8_t *ssid, size_t ssid_len, char *ssid_str,
33                     size_t ssid_str_len) {
34   if (ssid_str_len < ssid_len + 1) {
35     return false;
36   }
37   // Verify that the ssid is entirely printable characters and ASCII spaces.
38   for (uint8_t i = 0; i < ssid_len; i++) {
39     if (!std::isgraph(ssid[i]) && ssid[i] != ' ') {
40       return false;
41     }
42   }
43 
44   std::memcpy(ssid_str, ssid, ssid_len);
45   ssid_str[ssid_len] = '\0';
46   return true;
47 }
48 
ParseBssidToStr(const uint8_t bssid[CHRE_WIFI_BSSID_LEN],char * bssid_str,size_t bssid_str_len)49 bool ParseBssidToStr(const uint8_t bssid[CHRE_WIFI_BSSID_LEN], char *bssid_str,
50                      size_t bssid_str_len) {
51   if (bssid_str_len < kBssidStrLen) {
52     return false;
53   }
54 
55   const char *kFormat = "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8
56                         ":%02" PRIx8 ":%02" PRIx8;
57   std::snprintf(bssid_str, bssid_str_len, kFormat, bssid[0], bssid[1], bssid[2],
58                 bssid[3], bssid[4], bssid[5]);
59   return true;
60 }
61 
ParseChreWifiBand(uint8_t band)62 const char *ParseChreWifiBand(uint8_t band) {
63   switch (band) {
64     case CHRE_WIFI_BAND_2_4_GHZ:
65       return "2.4GHz";
66     case CHRE_WIFI_BAND_5_GHZ:
67       return "5GHz";
68     default:
69       return "<invalid>";
70   }
71 }
72 
73 }  // namespace
74 
Ieee80211FrequencyToChannel(int freq)75 int Ieee80211FrequencyToChannel(int freq) {
76   /* see 802.11-2007 17.3.8.3.2 and Annex J */
77   if (freq == 2484)
78     return 14;
79   else if (freq < 2484)
80     return (freq - 2407) / 5;
81   else if (freq >= 4910 && freq <= 4980)
82     return (freq - 4000) / 5;
83   else if (freq <= 45000) /* DMG band lower limit */
84     return (freq - 5000) / 5;
85   else if (freq >= 58320 && freq <= 64800)
86     return (freq - 56160) / 2160;
87   else
88     return 0;
89 }
90 
LogSsid(const uint8_t * ssid,uint8_t ssid_len)91 void LogSsid(const uint8_t *ssid, uint8_t ssid_len) {
92   const char *ssid_str = "<non-printable>";
93   char ssid_buffer[std::max<size_t>(kMaxSsidStrLen,
94                                     CHRE_WIFI_SSID_MAX_LEN * 3)];
95   if (ssid_len == 0) {
96     ssid_str = "<empty>";
97   } else if (ParseSsidToStr(ssid, ssid_len, ssid_buffer, kMaxSsidStrLen)) {
98     ssid_str = ssid_buffer;
99   } else {
100     // ssid has non-printable ASCII chars, parse in hex format
101     char *buf_ptr = ssid_buffer;
102     for (size_t i = 0; i < ssid_len; i++) {
103       buf_ptr += std::sprintf(buf_ptr, "%02" PRIx8 ":", ssid[i]);
104     }
105     buf_ptr[-1] = '\0';
106     ssid_str = ssid_buffer;
107   }
108   LOGI("  ssid: %s", ssid_str);
109 }
110 
LogBssid(const uint8_t * bssid)111 void LogBssid(const uint8_t *bssid) {
112   const char *bssid_str = "<non-printable>";
113   char bssidBuffer[kBssidStrLen];
114   if (ParseBssidToStr(bssid, bssidBuffer, kBssidStrLen)) {
115     bssid_str = bssidBuffer;
116   }
117   LOGI("  bssid: %s", bssid_str);
118 }
119 
LogChreScanResult(const chreWifiScanResult & result)120 void LogChreScanResult(const chreWifiScanResult &result) {
121   LOGI("chreWifiScanResult:");
122   LogSsid(result.ssid, result.ssidLen);
123   LOGI("  age (ms): %" PRIu32, result.ageMs);
124   LOGI("  capability info: 0x%" PRIx16, result.capabilityInfo);
125   LogBssid(result.bssid);
126   LOGI("  flags: 0x%" PRIx8, result.flags);
127   LOGI("  rssi: %" PRId8 "dBm", result.rssi);
128   LOGI("  band: %s (%" PRIu8 ")", ParseChreWifiBand(result.band), result.band);
129   LOGI("  primary channel: %" PRIu32, result.primaryChannel);
130   LOGI("  center frequency primary: %" PRIu32, result.centerFreqPrimary);
131   LOGI("  center frequency secondary: %" PRIu32, result.centerFreqSecondary);
132   LOGI("  channel width: %" PRIu8, result.channelWidth);
133   LOGI("  security mode: %" PRIu8, result.securityMode);
134 }
135 
GetErrorCodeName(ErrorCode error_code)136 const char *GetErrorCodeName(ErrorCode error_code) {
137   switch (error_code) {
138     case SUCCESS:
139       return "SUCCESS";
140     case FAILED_TO_ALLOCATE_MESSAGE_BUFFER:
141       return "FAILED_TO_ALLOCATE_MESSAGE_BUFFER";
142     case FAILED_TO_SERIALIZE_MESSAGE:
143       return "FAILED_TO_SERIALIZE_MESSAGE";
144     case FAILED_TO_SEND_MESSAGE:
145       return "FAILED_TO_SEND_MESSAGE";
146     case FAILED_TO_DESERIALIZE_SCAN_CONFIG:
147       return "FAILED_TO_DESERIALIZE_SCAN_CONFIG";
148     case INVALID_SUBSCRIBE_MESSAGE_SIZE:
149       return "INVALID_SUBSCRIBE_MESSAGE_SIZE";
150     case SCAN_CONFIG_NOT_INITIALIZED:
151       return "SCAN_CONFIG_NOT_INITIALIZED";
152     case UNSPECIFIED_HOST_ENDPOINT:
153       return "UNSPECIFIED_HOST_ENDPOINT";
154     case FAILED_TO_SEND_SCAN_RESULTS:
155       return "FAILED_TO_SEND_SCAN_RESULTS";
156     case FAILED_TO_SEND_SCAN_STATS:
157       return "FAILED_TO_SEND_SCAN_STATS";
158     case SCAN_MONITORING_NOT_SUPPORTED:
159       return "SCAN_MONITORING_NOT_SUPPORTED";
160     case FAILED_TO_START_SCAN_MONITORING:
161       return "FAILED_TO_START_SCAN_MONITORING";
162     case FAILED_TO_STOP_SCAN_MONITORING:
163       return "FAILED_TO_STOP_SCAN_MONITORING";
164     case FAILED_TO_CONFIGURE_SCAN_MONITORING_ASYNC:
165       return "FAILED_TO_CONFIGURE_SCAN_MONITORING_ASYNC";
166     case ONDEMAND_SCAN_NOT_SUPPORTED:
167       return "ONDEMAND_SCAN_NOT_SUPPORTED";
168     case FAILED_TO_SEND_ONDEMAND_SCAN_REQUEST:
169       return "FAILED_TO_SEND_ONDEMAND_SCAN_REQUEST";
170     case FAILED_TO_SEND_ONDEMAND_SCAN_REQUEST_ASYNC:
171       return "FAILED_TO_SEND_ONDEMAND_SCAN_REQUEST_ASYNC";
172     case OUT_OF_ORDER_SCAN_RESULTS:
173       return "OUT_OF_ORDER_SCAN_RESULTS";
174     case INCOMPLETE_SCAN_RESULTS_BEFORE_SCAN_REQUEST:
175       return "INCOMPLETE_SCAN_RESULTS_BEFORE_SCAN_REQUEST";
176     case FAILED_TO_SET_SCAN_TIMER:
177       return "FAILED_TO_SET_SCAN_TIMER";
178     default:
179       return "UNKNOWN_ERROR";
180   }
181 }
182 
183 }  // namespace utility
184 }  // namespace wifi_offload
185