Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
/*******************************************************************************
* File Name: scan_task.c
*
* Description: This file contains functions that perform network related tasks
* like connecting to an AP, scanning for APs, connection event callbacks, and
* utility function for printing scan results.
*
* Related Document: See README.md
*
*
*******************************************************************************
* $ Copyright 2021-2023 Cypress Semiconductor $
*******************************************************************************/
/*******************************************************************************
* Header file includes
******************************************************************************/
#include "cybsp.h"
#include "cyhal.h"
#include <inttypes.h>
#include <string.h>
/* FreeRTOS header file.*/
#include "FreeRTOS.h"
/*Wi-Fi Connection Manager header file.*/
#include "cy_wcm.h"
/*Task header file*/
#include "scan_task.h"
/*******************************************************************************
* Global Variables
******************************************************************************/
/*Task handler*/
TaskHandle_t scan_task_handle;
/* This variable holds the value of the total number of the scan results that is
* available in the scan callback function in the current scan.
*/
uint32_t num_scan_result;
/* This is used to decide the type of scan filter to be used. The valid values
* are provided in the enumeration scan_filter_mode.
*/
enum scan_filter_mode scan_filter_mode_select = SCAN_FILTER_NONE;
/* This is used to decide the band to be used for the scan filter
*/
const char* band_string[] =
{
[CY_WCM_WIFI_BAND_ANY] = "2.4 and 5 GHz",
[CY_WCM_WIFI_BAND_2_4GHZ] = "2.4 GHz",
[CY_WCM_WIFI_BAND_5GHZ] = "5 GHz"
};
bool is_retarget_io_initialized = false;
bool is_led_initialized = false;
/* Bit map for error in scan arguments.
* Bit 0: SSID Error; Bit 1: RSSI value error
*/
cy_rslt_t bit_map_scan_args = 0;
typedef enum
{
SSID_LENGTH_ERROR = (1 << 0),
RSSI_VALUE_ERROR = (1 << 1),
} scan_args_error_t;
/*******************************************************************************
* Function Prototypes
******************************************************************************/
static void scan_callback( cy_wcm_scan_result_t *result_ptr, void *user_data, cy_wcm_scan_status_t status );
static void print_scan_result(cy_wcm_scan_result_t *result);
void print_heap_usage(char *msg);
/*******************************************************************************
* Function Name: validate_scan_arguments
*******************************************************************************
* Summary: This function validates the length of the SSID and value of the
* RSSI range.
*
* Parameters:
* uint8_t ssid_len: Length of SSID.
*
* Return:
* cy_rslt_t: Returns the bit map result for error detection
*
******************************************************************************/
cy_rslt_t validate_scan_arguments(uint8_t ssid_len)
{
/*Validate the length of SSID*/
if(ssid_len == 0 || ssid_len > CY_WCM_MAX_SSID_LEN )
{
bit_map_scan_args |= SSID_LENGTH_ERROR;
}
/* Validate the RSSI Range */
if((SCAN_FOR_RSSI_VALUE != CY_WCM_SCAN_RSSI_EXCELLENT) &&
(SCAN_FOR_RSSI_VALUE != CY_WCM_SCAN_RSSI_GOOD) &&
(SCAN_FOR_RSSI_VALUE != CY_WCM_SCAN_RSSI_FAIR))
{
bit_map_scan_args |= RSSI_VALUE_ERROR;
}
return bit_map_scan_args;
}
/*******************************************************************************
* Function Name: scan_task
*******************************************************************************
* Summary: This task initializes the Wi-Fi device, Wi-Fi transport, lwIP
* network stack, and issues a scan for the available networks. A scan filter
* is applied depending on the value of scan_filter_mode_select. After starting
* the scan, it waits for the notification from the scan callback for completion
* of the scan. It then waits for a delay specified by SCAN_DELAY_PERIOD_MS
* before repeating the process.
*
*
* Parameters:
* void* arg: Pointer to an argument passed during task creation (unused).
*
* Return:
* void
*
******************************************************************************/
void scan_task(void *arg)
{
CY_UNUSED_PARAMETER(arg);
uint8_t ssid_len = (uint8_t)strlen(SCAN_FOR_SSID_VALUE);
cy_wcm_scan_filter_t scan_filter;
cy_rslt_t result = CY_RSLT_SUCCESS;
cy_wcm_config_t wcm_config = { .interface = CY_WCM_INTERFACE_TYPE_STA };
cy_wcm_mac_t scan_for_mac_value = {SCAN_FOR_MAC_ADDRESS};
memset(&scan_filter, 0, sizeof(cy_wcm_scan_filter_t));
result = cy_wcm_init(&wcm_config);
error_handler(result, "Failed to initialize Wi-Fi Connection Manager.\n");
result = validate_scan_arguments(ssid_len);
while (true)
{
/* Select the type of filter to use.*/
switch (scan_filter_mode_select)
{
case SCAN_FILTER_NONE:
APP_INFO(("Scanning without any filter\n"));
break;
case SCAN_FILTER_SSID:
if (result & SSID_LENGTH_ERROR)
{
ERR_INFO(("SSID length should be <= 32 bytes\n"));
}
else
{
APP_INFO(("Scanning for %s.\n", SCAN_FOR_SSID_VALUE));
/* Configure the scan filter for SSID specified by
* SCAN_FOR_SSID_VALUE.
* Max SSID length is 32 bytes.
*/
scan_filter.mode = CY_WCM_SCAN_FILTER_TYPE_SSID;
memcpy(scan_filter.param.SSID, SCAN_FOR_SSID_VALUE, sizeof(SCAN_FOR_SSID_VALUE));
}
break;
case SCAN_FILTER_RSSI:
if (result & RSSI_VALUE_ERROR)
{
ERR_INFO(("Invalid RSSI value provided.\n"));
}
else
{
APP_INFO(("Scanning for RSSI > %d dBm.\n", SCAN_FOR_RSSI_VALUE));
/* Configure the scan filter for RSSI range specified by
* SCAN_FOR_RSSI_VALUE.
*/
scan_filter.mode = CY_WCM_SCAN_FILTER_TYPE_RSSI;
scan_filter.param.rssi_range = SCAN_FOR_RSSI_VALUE;
}
break;
case SCAN_FILTER_MAC:
APP_INFO(("Scanning for %02X:%02X:%02X:%02X:%02X:%02X.\n", scan_for_mac_value[0], scan_for_mac_value[1], scan_for_mac_value[2], scan_for_mac_value[3], scan_for_mac_value[4], scan_for_mac_value[5]));
/* Configure the scan filter for MAC specified by scan_for_mac_value
* MAC address length is 6 bytes
*/
scan_filter.mode = CY_WCM_SCAN_FILTER_TYPE_MAC;
memcpy(scan_filter.param.BSSID, &scan_for_mac_value, sizeof(scan_for_mac_value));
break;
case SCAN_FILTER_BAND:
APP_INFO(("Scanning in %s band.\n", band_string[SCAN_FOR_BAND_VALUE]));
/* Configure the scan filter for band specified by
* SCAN_FOR_BAND_VALUE.
*/
scan_filter.mode = CY_WCM_SCAN_FILTER_TYPE_BAND;
scan_filter.param.band = SCAN_FOR_BAND_VALUE;
break;
default:
break;
}
PRINT_SCAN_TEMPLATE();
if(SCAN_FILTER_NONE == scan_filter_mode_select)
{
result = cy_wcm_start_scan(scan_callback, NULL, NULL);
}
else
{
result = cy_wcm_start_scan(scan_callback, NULL, &scan_filter);
}
/* Wait for scan completion if scan was started successfully. The API
* cy_wcm_start_scan doesn't wait for scan completion. If it is called
* again when the scan hasn't completed, the API returns
* CY_WCM_RESULT_SCAN_IN_PROGRESS.
*/
if (CY_RSLT_SUCCESS == result)
{
xTaskNotifyWait(0, 0, NULL, portMAX_DELAY);
}
/* Define PRINT_HEAP_USAGE using DEFINES variable in the Makefile. */
print_heap_usage("After scan results are printed to UART");
vTaskDelay(pdMS_TO_TICKS(SCAN_DELAY_MS));
}
}
/*******************************************************************************
* Function Name: scan_callback
*******************************************************************************
* Summary: The callback function which accumulates the scan results. After
* completing the scan, it sends a task notification to scan_task.
*
* Parameters:
* cy_wcm_scan_result_t *result_ptr: Pointer to the scan result
* void *user_data: User data.
* cy_wcm_scan_status_t status: Status of scan completion.
*
* Return:
* void
*
******************************************************************************/
static void scan_callback(cy_wcm_scan_result_t *result_ptr, void *user_data, cy_wcm_scan_status_t status)
{
if ((strlen((const char *)result_ptr->SSID) != 0) && (status == CY_WCM_SCAN_INCOMPLETE))
{
num_scan_result++;
print_scan_result(result_ptr);
}
if ( (CY_WCM_SCAN_COMPLETE == status) )
{
/* Reset the number of scan results to 0 for the next scan.*/
num_scan_result = 0;
/* Notify that scan has completed.*/
xTaskNotify(scan_task_handle, 0, eNoAction);
}
}
/*******************************************************************************
* Function Name: print_scan_result
*******************************************************************************
* Summary: This function prints the scan result accumulated by the scan
* handler.
*
*
* Parameters:
* cy_wcm_scan_result_t *result: Pointer to the scan result.
*
* Return:
* void
*
******************************************************************************/
static void print_scan_result(cy_wcm_scan_result_t *result)
{
char* security_type_string;
/* Convert the security type of the scan result to the corresponding
* security string
*/
switch (result->security)
{
case CY_WCM_SECURITY_OPEN:
security_type_string = SECURITY_OPEN;
break;
case CY_WCM_SECURITY_WEP_PSK:
security_type_string = SECURITY_WEP_PSK;
break;
case CY_WCM_SECURITY_WEP_SHARED:
security_type_string = SECURITY_WEP_SHARED;
break;
case CY_WCM_SECURITY_WPA_TKIP_PSK:
security_type_string = SECURITY_WEP_TKIP_PSK;
break;
case CY_WCM_SECURITY_WPA_AES_PSK:
security_type_string = SECURITY_WPA_AES_PSK;
break;
case CY_WCM_SECURITY_WPA_MIXED_PSK:
security_type_string = SECURITY_WPA_MIXED_PSK;
break;
case CY_WCM_SECURITY_WPA2_AES_PSK:
security_type_string = SECURITY_WPA2_AES_PSK;
break;
case CY_WCM_SECURITY_WPA2_TKIP_PSK:
security_type_string = SECURITY_WPA2_TKIP_PSK;
break;
case CY_WCM_SECURITY_WPA2_MIXED_PSK:
security_type_string = SECURITY_WPA2_MIXED_PSK;
break;
case CY_WCM_SECURITY_WPA2_FBT_PSK:
security_type_string = SECURITY_WPA2_FBT_PSK;
break;
case CY_WCM_SECURITY_WPA3_SAE:
security_type_string = SECURITY_WPA3_SAE;
break;
case CY_WCM_SECURITY_WPA3_WPA2_PSK:
security_type_string = SECURITY_WPA3_WPA2_PSK;
break;
case CY_WCM_SECURITY_IBSS_OPEN:
security_type_string = SECURITY_IBSS_OPEN;
break;
case CY_WCM_SECURITY_WPS_SECURE:
security_type_string = SECURITY_WPS_SECURE;
break;
case CY_WCM_SECURITY_UNKNOWN:
security_type_string = SECURITY_UNKNOWN;
break;
case CY_WCM_SECURITY_WPA2_WPA_AES_PSK:
security_type_string = SECURITY_WPA2_WPA_AES_PSK;
break;
case CY_WCM_SECURITY_WPA2_WPA_MIXED_PSK:
security_type_string = SECURITY_WPA2_WPA_MIXED_PSK;
break;
case CY_WCM_SECURITY_WPA_TKIP_ENT:
security_type_string = SECURITY_WPA_TKIP_ENT;
break;
case CY_WCM_SECURITY_WPA_AES_ENT:
security_type_string = SECURITY_WPA_AES_ENT;
break;
case CY_WCM_SECURITY_WPA_MIXED_ENT:
security_type_string = SECURITY_WPA_MIXED_ENT;
break;
case CY_WCM_SECURITY_WPA2_TKIP_ENT:
security_type_string = SECURITY_WPA2_TKIP_ENT;
break;
case CY_WCM_SECURITY_WPA2_AES_ENT:
security_type_string = SECURITY_WPA2_AES_ENT;
break;
case CY_WCM_SECURITY_WPA2_MIXED_ENT:
security_type_string = SECURITY_WPA2_MIXED_ENT;
break;
case CY_WCM_SECURITY_WPA2_FBT_ENT:
security_type_string = SECURITY_WPA2_FBT_ENT;
break;
default:
security_type_string = SECURITY_UNKNOWN;
break;
}
printf(" %2"PRIu32" %-32s %4d %2d %02X:%02X:%02X:%02X:%02X:%02X %-15s\n",
num_scan_result, result->SSID,
result->signal_strength, result->channel, result->BSSID[0], result->BSSID[1],
result->BSSID[2], result->BSSID[3], result->BSSID[4], result->BSSID[5],
security_type_string);
}
/*******************************************************************************
* Function Name: gpio_interrupt_handler
*******************************************************************************
* Summary:
* GPIO interrupt service routine. This function detects button presses and
* changes the type of the applied scan filter.
*
* Parameters:
* void *handler_arg : pointer to the variable passed to the ISR (unused)
* cyhal_gpio_event_t event : GPIO event type (unused)
*
* Return:
* void
*
*******************************************************************************/
void gpio_interrupt_handler(void *handler_arg, cyhal_gpio_event_t event)
{
CY_UNUSED_PARAMETER(handler_arg);
CY_UNUSED_PARAMETER(event);
/* Increment and check if the scan filter selected is invalid. If invalid,
* reset to no scan filter.
*/
if(++scan_filter_mode_select >= SCAN_FILTER_INVALID)
{
scan_filter_mode_select = SCAN_FILTER_NONE;
}
}
/*******************************************************************************
* Function Name: error_handler
********************************************************************************
*
* Summary:
* This function processes unrecoverable errors such as any component
* initialization errors etc. In case of such error, the system will halt the
* CPU.
*
* Parameters:
* cy_rslt_t result: contains the result of an operation.
* char* message: contains the error message that is printed to the serial
* terminal.
*
* Note: If error occurs, interrupts are disabled.
*
* Return:
* void
*
*******************************************************************************/
void error_handler(cy_rslt_t result, char* message)
{
if(CY_RSLT_SUCCESS != result)
{
if(is_led_initialized)
{
cyhal_gpio_write(CYBSP_USER_LED, CYBSP_LED_STATE_ON);
}
if( is_retarget_io_initialized && (NULL != message) )
{
ERR_INFO(("%s", message));
}
__disable_irq();
CY_ASSERT(0);
}
}
/* [] END OF FILE */