| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <algorithm> |
| #include <cctype> |
| |
| #include "chre/apps/wifi_offload/utility.h" |
| #include "chre/apps/wifi_offload/wifi_offload.h" |
| |
| namespace wifi_offload { |
| namespace utility { |
| namespace { |
| |
| // The length of a string SSID with null-terminator. |
| constexpr size_t kMaxSsidStrLen = CHRE_WIFI_SSID_MAX_LEN + 1; |
| // The length of a formatted BSSID string in XX:XX:XX:XX:XX:XX\0 format. |
| constexpr size_t kBssidStrLen = 18; |
| |
| bool ParseSsidToStr(const uint8_t *ssid, size_t ssid_len, char *ssid_str, |
| size_t ssid_str_len) { |
| if (ssid_str_len < ssid_len + 1) { |
| return false; |
| } |
| // Verify that the ssid is entirely printable characters and ASCII spaces. |
| for (uint8_t i = 0; i < ssid_len; i++) { |
| if (!std::isgraph(ssid[i]) && ssid[i] != ' ') { |
| return false; |
| } |
| } |
| |
| std::memcpy(ssid_str, ssid, ssid_len); |
| ssid_str[ssid_len] = '\0'; |
| return true; |
| } |
| |
| bool ParseBssidToStr(const uint8_t bssid[CHRE_WIFI_BSSID_LEN], char *bssid_str, |
| size_t bssid_str_len) { |
| if (bssid_str_len < kBssidStrLen) { |
| return false; |
| } |
| |
| const char *kFormat = "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 |
| ":%02" PRIx8 ":%02" PRIx8; |
| std::snprintf(bssid_str, bssid_str_len, kFormat, bssid[0], bssid[1], bssid[2], |
| bssid[3], bssid[4], bssid[5]); |
| return true; |
| } |
| |
| const char *ParseChreWifiBand(uint8_t band) { |
| switch (band) { |
| case CHRE_WIFI_BAND_2_4_GHZ: |
| return "2.4GHz"; |
| case CHRE_WIFI_BAND_5_GHZ: |
| return "5GHz"; |
| default: |
| return "<invalid>"; |
| } |
| } |
| |
| } // namespace |
| |
| int Ieee80211FrequencyToChannel(int freq) { |
| /* see 802.11-2007 17.3.8.3.2 and Annex J */ |
| if (freq == 2484) |
| return 14; |
| else if (freq < 2484) |
| return (freq - 2407) / 5; |
| else if (freq >= 4910 && freq <= 4980) |
| return (freq - 4000) / 5; |
| else if (freq <= 45000) /* DMG band lower limit */ |
| return (freq - 5000) / 5; |
| else if (freq >= 58320 && freq <= 64800) |
| return (freq - 56160) / 2160; |
| else |
| return 0; |
| } |
| |
| void LogSsid(const uint8_t *ssid, uint8_t ssid_len) { |
| const char *ssid_str = "<non-printable>"; |
| char |
| ssid_buffer[std::max<size_t>(kMaxSsidStrLen, CHRE_WIFI_SSID_MAX_LEN * 3)]; |
| if (ssid_len == 0) { |
| ssid_str = "<empty>"; |
| } else if (ParseSsidToStr(ssid, ssid_len, ssid_buffer, kMaxSsidStrLen)) { |
| ssid_str = ssid_buffer; |
| } else { |
| // ssid has non-printable ASCII chars, parse in hex format |
| char *buf_ptr = ssid_buffer; |
| for (size_t i = 0; i < ssid_len; i++) { |
| buf_ptr += std::sprintf(buf_ptr, "%02" PRIx8 ":", ssid[i]); |
| } |
| buf_ptr[-1] = '\0'; |
| ssid_str = ssid_buffer; |
| } |
| LOGI(" ssid: %s", ssid_str); |
| } |
| |
| void LogBssid(const uint8_t *bssid) { |
| const char *bssid_str = "<non-printable>"; |
| char bssidBuffer[kBssidStrLen]; |
| if (ParseBssidToStr(bssid, bssidBuffer, kBssidStrLen)) { |
| bssid_str = bssidBuffer; |
| } |
| LOGI(" bssid: %s", bssid_str); |
| } |
| |
| void LogChreScanResult(const chreWifiScanResult &result) { |
| LOGI("chreWifiScanResult:"); |
| LogSsid(result.ssid, result.ssidLen); |
| LOGI(" age (ms): %" PRIu32, result.ageMs); |
| LOGI(" capability info: 0x%" PRIx16, result.capabilityInfo); |
| LogBssid(result.bssid); |
| LOGI(" flags: 0x%" PRIx8, result.flags); |
| LOGI(" rssi: %" PRId8 "dBm", result.rssi); |
| LOGI(" band: %s (%" PRIu8 ")", ParseChreWifiBand(result.band), result.band); |
| LOGI(" primary channel: %" PRIu32, result.primaryChannel); |
| LOGI(" center frequency primary: %" PRIu32, result.centerFreqPrimary); |
| LOGI(" center frequency secondary: %" PRIu32, result.centerFreqSecondary); |
| LOGI(" channel width: %" PRIu8, result.channelWidth); |
| LOGI(" security mode: %" PRIu8, result.securityMode); |
| } |
| |
| const char *GetErrorCodeName(ErrorCode error_code) { |
| switch (error_code) { |
| case SUCCESS: |
| return "SUCCESS"; |
| case FAILED_TO_ALLOCATE_MESSAGE_BUFFER: |
| return "FAILED_TO_ALLOCATE_MESSAGE_BUFFER"; |
| case FAILED_TO_SERIALIZE_MESSAGE: |
| return "FAILED_TO_SERIALIZE_MESSAGE"; |
| case FAILED_TO_SEND_MESSAGE: |
| return "FAILED_TO_SEND_MESSAGE"; |
| case FAILED_TO_DESERIALIZE_SCAN_CONFIG: |
| return "FAILED_TO_DESERIALIZE_SCAN_CONFIG"; |
| case INVALID_SUBSCRIBE_MESSAGE_SIZE: |
| return "INVALID_SUBSCRIBE_MESSAGE_SIZE"; |
| case SCAN_CONFIG_NOT_INITIALIZED: |
| return "SCAN_CONFIG_NOT_INITIALIZED"; |
| case UNSPECIFIED_HOST_ENDPOINT: |
| return "UNSPECIFIED_HOST_ENDPOINT"; |
| case FAILED_TO_SEND_SCAN_RESULTS: |
| return "FAILED_TO_SEND_SCAN_RESULTS"; |
| case FAILED_TO_SEND_SCAN_STATS: |
| return "FAILED_TO_SEND_SCAN_STATS"; |
| case SCAN_MONITORING_NOT_SUPPORTED: |
| return "SCAN_MONITORING_NOT_SUPPORTED"; |
| case FAILED_TO_START_SCAN_MONITORING: |
| return "FAILED_TO_START_SCAN_MONITORING"; |
| case FAILED_TO_STOP_SCAN_MONITORING: |
| return "FAILED_TO_STOP_SCAN_MONITORING"; |
| case FAILED_TO_CONFIGURE_SCAN_MONITORING_ASYNC: |
| return "FAILED_TO_CONFIGURE_SCAN_MONITORING_ASYNC"; |
| case ONDEMAND_SCAN_NOT_SUPPORTED: |
| return "ONDEMAND_SCAN_NOT_SUPPORTED"; |
| case FAILED_TO_SEND_ONDEMAND_SCAN_REQUEST: |
| return "FAILED_TO_SEND_ONDEMAND_SCAN_REQUEST"; |
| case FAILED_TO_SEND_ONDEMAND_SCAN_REQUEST_ASYNC: |
| return "FAILED_TO_SEND_ONDEMAND_SCAN_REQUEST_ASYNC"; |
| case OUT_OF_ORDER_SCAN_RESULTS: |
| return "OUT_OF_ORDER_SCAN_RESULTS"; |
| case INCOMPLETE_SCAN_RESULTS_BEFORE_SCAN_REQUEST: |
| return "INCOMPLETE_SCAN_RESULTS_BEFORE_SCAN_REQUEST"; |
| case FAILED_TO_SET_SCAN_TIMER: |
| return "FAILED_TO_SET_SCAN_TIMER"; |
| default: |
| return "UNKNOWN_ERROR"; |
| } |
| } |
| |
| } // namespace utility |
| } // namespace wifi_offload |