rv1126-external/wifiAutoSetup/easy_setup_rtos.c

441 lines
15 KiB
C

/*
* $ Copyright Broadcom Corporation $
*/
/** @file
*
*/
#include "wiced.h"
#include "stdint.h"
#include "stddef.h"
#include "wwd_network_interface.h"
#include "wwd_buffer_interface.h"
#include "tlv.h"
#include "wiced_security.h"
#include "internal/wwd_sdpcm.h"
#include "wwd_wlioctl.h"
#include "wwd_events.h"
#include "easy_setup.h"
#define PARAM_MAX_LEN (256)
#define RESULT_MAX_LEN (256)
typedef struct
{
easy_setup_result_t result;
easy_setup_param_t param;
wiced_semaphore_t es_complete;
wiced_semaphore_t scan_complete;
wiced_security_t security;
uint8_t channel;
int abort_scan;
uint8_t protocol;
} easy_setup_workspace_t;
// Trigger custom scan to fetch the security info of the AP
#define SCAN_TO_GET_SECURITY
#ifdef SCAN_TO_GET_SECURITY
static wiced_scan_result_t scan_result[1];
#endif
/* error code in WICED/WWD/include/wwd_constants.h */
#define easy_setup_assert(s, v) \
do {\
if (v != WWD_SUCCESS) {\
WPRINT_WICED_INFO(("%s, %s: %d\n", __FUNCTION__, s, v));\
WICED_ASSERTION_FAIL_ACTION();\
}\
} while (0)
#define CHECK_IOCTL_BUFFER( buff ) \
if ( buff == NULL ) { \
easy_setup_assert("Allocation failed", WWD_BUFFER_UNAVAILABLE_TEMPORARY);\
return WWD_BUFFER_ALLOC_FAIL; \
}
static const wwd_event_num_t easy_setup_events[] = { WLC_E_WAKE_EVENT, WLC_E_NONE };
uint16_t g_protocol_mask = 0x3; /* mcast+neeze */
static uint8_t g_protocol = 0;
static void* easy_setup_result_handler( const wwd_event_header_t* event_header,
const uint8_t* event_data,
void* handler_user_data )
{
easy_setup_workspace_t *ws = (easy_setup_workspace_t *)handler_user_data;
if (event_header->status == WLC_E_STATUS_SUCCESS)
{
WPRINT_WICED_INFO( ("\r\nEvent Found => Success\r\n") );
memcpy( &ws->result, event_data, sizeof(easy_setup_result_t) );
wiced_rtos_set_semaphore( &ws->es_complete );
//easy_setup_stop( );
}
else if (event_header->status == WLC_E_STATUS_TIMEOUT)
{
WPRINT_WICED_INFO( ("\r\nEvent Found => Timeout\r\n") );
}
else
{
WPRINT_WICED_INFO( ("\r\nEvent Found => Unknown\r\n") );
}
return handler_user_data;
}
wwd_result_t easy_setup_restart( void )
{
wiced_buffer_t buffer;
wwd_result_t result;
easy_setup_param_t *param;
param = wwd_sdpcm_get_iovar_buffer( &buffer, sizeof(easy_setup_param_t), "easy_setup");
CHECK_IOCTL_BUFFER( param );
param->enable = EASY_SETUP_RESTART;
result = wwd_sdpcm_send_iovar( SDPCM_SET, buffer, 0, WWD_STA_INTERFACE );
easy_setup_assert("Failed to set IOCTL", result);
return result;
}
int easy_setup_stop( void )
{
wiced_buffer_t buffer;
wwd_result_t result;
easy_setup_param_t *p;
p = wwd_sdpcm_get_iovar_buffer( &buffer, sizeof(easy_setup_param_t), "easy_setup");
CHECK_IOCTL_BUFFER(p);
p->enable = EASY_SETUP_STOP;
result = wwd_sdpcm_send_iovar( SDPCM_SET, buffer, 0, WWD_STA_INTERFACE );
easy_setup_assert("Failed to set IOCTL", result);
return result;
}
wwd_result_t easy_setup_enable( uint16_t proto_mask, easy_setup_workspace_t *ws )
{
wiced_buffer_t buffer;
wwd_result_t result;
easy_setup_param_t *p;
result = wwd_management_set_event_handler( easy_setup_events, easy_setup_result_handler, ws, WWD_STA_INTERFACE );
easy_setup_assert("Failed to set Event Handler", result);
p = wwd_sdpcm_get_iovar_buffer( &buffer, PARAM_MAX_LEN, "easy_setup");
CHECK_IOCTL_BUFFER(p);
p->enable = EASY_SETUP_START;
p->protocol_mask = proto_mask;
int param_len = 0;
param_len += ((uint8*)&p->param-(uint8*)p);
tlv_t* t = &p->param;
easy_setup_get_param(proto_mask, &t);
result = wwd_sdpcm_send_iovar( SDPCM_SET, buffer, 0, WWD_STA_INTERFACE);
easy_setup_assert("Failed to set IOCTL", result);
return result;
}
int easy_setup_query( easy_setup_workspace_t *ws )
{
wiced_buffer_t buffer;
wiced_buffer_t response;
wwd_result_t ret;
easy_setup_result_t* r = &ws->result;
UNUSED_PARAMETER(ws);
(void)wwd_sdpcm_get_iovar_buffer(&buffer, RESULT_MAX_LEN, "easy_setup");
ret = wwd_sdpcm_send_iovar(SDPCM_GET, buffer, &response, WWD_STA_INTERFACE );
if ( ret == WWD_SUCCESS )
{
tlv_t* t = (tlv_t*) host_buffer_get_current_piece_data_pointer(response);
memcpy(r, t->value, sizeof(easy_setup_result_t));
WPRINT_WICED_INFO( ("state [%d]\r\n", r->state) );
if (r->state == EASY_SETUP_STATE_DONE)
{
WPRINT_WICED_INFO(("Finished! protocol: %d\r\n", t->type));
g_protocol = t->type;
easy_setup_set_result(g_protocol, t->value);
wiced_rtos_set_semaphore( &ws->es_complete );
}
host_buffer_release(response, WWD_NETWORK_RX);
}
return WICED_SUCCESS;
}
#ifdef SCAN_TO_GET_SECURITY
static void scan_result_callback( wiced_scan_result_t** result_ptr, void* user_data, wiced_scan_status_t status )
{
easy_setup_workspace_t *ws = (easy_setup_workspace_t *)user_data;
UNUSED_PARAMETER(status);
if (ws->abort_scan == WICED_TRUE) {
return;
}
if (NULL == result_ptr)
{
wiced_rtos_set_semaphore(&ws->scan_complete);
}
else
{
/*
uint8_t* o = (*result_ptr)->BSSID.octet;
WPRINT_WICED_INFO( ("scan cb, %02x:%02x:%02x:%02x:%02x:%02x\r\n", o[0], o[1], o[2], o[3], o[4], o[5]) );
*/
/* Only look for a match on our locked BSSID */
if (memcmp(ws->result.ap_bssid.octet, (*result_ptr)->BSSID.octet, sizeof(wiced_mac_t)) == 0)
{
ws->abort_scan = WICED_TRUE;
ws->channel = (*result_ptr)->channel;
ws->security = (*result_ptr)->security;
wiced_rtos_set_semaphore(&ws->scan_complete);
}
}
}
#endif
static int hex_str_to_int( const char* hex_str )
{
int n = 0;
uint32_t value = 0;
int shift = 7;
while ( hex_str[n] != '\0' && n < 8 )
{
if ( hex_str[n] > 0x21 && hex_str[n] < 0x40 )
{
value |= (uint32_t)(( hex_str[n] & 0x0f ) << ( shift << 2 ));
}
else if ( ( hex_str[n] >= 'a' && hex_str[n] <= 'f' ) || ( hex_str[n] >= 'A' && hex_str[n] <= 'F' ) )
{
value |= (uint32_t)(( ( hex_str[n] & 0x0f ) + 9 ) << ( shift << 2 ));
}
else
{
break;
}
n++;
shift--;
}
return (int)( value >> ( ( shift + 1 ) << 2 ) );
}
int easy_setup_start()
{
easy_setup_workspace_t* ws = NULL;
easy_setup_result_t *result = NULL;
wiced_bool_t led_flag;
wiced_config_ap_entry_t* dct_ap_entry;
#ifdef SCAN_TO_GET_SECURITY
wiced_mac_t bogus_scan_mac;
wiced_ssid_t ssid;
wiced_scan_extended_params_t extparam = { 5, 110, 110, 50 };
wiced_scan_result_t* result_ptr = (wiced_scan_result_t *) &scan_result;
int retry_times;
#endif
#ifdef AUTO_TEST
int timeout_count = 0;
#endif
if (!g_protocol_mask) {
WPRINT_WICED_INFO(("No protocol enabled.\r\n"));
return WICED_ERROR;
}
ws = malloc_named( "es", sizeof(easy_setup_workspace_t) );
if ( ws == NULL )
{
return WICED_OUT_OF_HEAP_SPACE;
}
memset(ws, 0, sizeof(easy_setup_workspace_t));
ws->abort_scan = WICED_FALSE;
wiced_rtos_init_semaphore( &ws->es_complete);
easy_setup_enable(g_protocol_mask, ws);
WPRINT_WICED_INFO( ("Enabled, waiting ...\r\n") );
led_flag = WICED_FALSE;
while (wiced_rtos_get_semaphore( &ws->es_complete, 500 * MILLISECONDS ) == WICED_TIMEOUT)
{
/* LED show status, could be removed */
if ( led_flag == WICED_FALSE )
{
led_flag = WICED_TRUE;
wiced_gpio_output_high( WICED_LED1 );
}
else
{
led_flag = WICED_FALSE;
wiced_gpio_output_low( WICED_LED1 );
}
easy_setup_query( ws );
#ifdef AUTO_TEST
timeout_count++;
/* if each takes 500ms, then 60 means wait time is 500ms x 60 = 30s */
if (timeout_count == 60)
{
wiced_rtos_set_semaphore( &ws->es_complete );
easy_setup_stop( );
wiced_rtos_deinit_semaphore( &ws->es_complete );
return WWD_TIMEOUT;
}
#endif
}
wwd_management_set_event_handler( easy_setup_events, NULL, NULL, WWD_STA_INTERFACE );
wiced_rtos_deinit_semaphore( &ws->es_complete );
easy_setup_stop( );
/* LED show status, could be removed */
wiced_gpio_output_high( WICED_LED1 );
result = &ws->result;
result->security_key[result->security_key_length] = 0;
WPRINT_WICED_INFO( ("SSID : %s\r\n", result->ap_ssid.val) );
WPRINT_WICED_INFO( ("PASSWORD : %.64s\r\n", result->security_key) );
WPRINT_WICED_INFO( ("BSSID : %02x:%02x:%02x:%02x:%02x:%02x\r\n",
(uint)result->ap_bssid.octet[0], (uint)result->ap_bssid.octet[1],
(uint)result->ap_bssid.octet[2], (uint)result->ap_bssid.octet[3],
(uint)result->ap_bssid.octet[4], (uint)result->ap_bssid.octet[5]));
wiced_rtos_init_semaphore(&ws->scan_complete);
wiced_rtos_get_semaphore( &ws->scan_complete, 200 * MILLISECONDS );
#ifdef SCAN_TO_GET_SECURITY
memcpy( &bogus_scan_mac, &result->ap_bssid, sizeof(wiced_mac_t) );
memcpy( &ssid, &result->ap_ssid, sizeof(wiced_ssid_t) );
wiced_rtos_init_semaphore( &ws->scan_complete );
result_ptr = &scan_result[0];
/* we need to scan and get security & channel, will retry several times */
retry_times = 3;
do {
wwd_wifi_scan( WICED_SCAN_TYPE_ACTIVE, WICED_BSS_TYPE_INFRASTRUCTURE, &ssid, NULL, NULL, &extparam, scan_result_callback, (wiced_scan_result_t **) &result_ptr, ws, WWD_STA_INTERFACE );
wiced_rtos_get_semaphore( &ws->scan_complete, 2000 * MILLISECONDS );
retry_times--;
} while ((ws->channel == 0) && (retry_times > 0));
WPRINT_WICED_INFO( ("AP Channel : %d\r\n", ws->channel) );
WPRINT_WICED_INFO( ("AP Security : %s ",
ws->security == WICED_SECURITY_OPEN ? "Open" :
ws->security == WICED_SECURITY_WEP_PSK ? "WEP-OPEN" :
ws->security == WICED_SECURITY_WEP_SHARED ? "WEP-SHARED" :
ws->security == WICED_SECURITY_WPA_TKIP_PSK ? "WPA-PSK TKIP" :
ws->security == WICED_SECURITY_WPA_AES_PSK ? "WPA-PSK AES" :
ws->security == WICED_SECURITY_WPA2_AES_PSK ? "WPA2-PSK AES" :
ws->security == WICED_SECURITY_WPA2_TKIP_PSK ? "WPA2-PSK TKIP" :
ws->security == WICED_SECURITY_WPA2_MIXED_PSK ? "WPA2-PSK Mixed" :
"Unknown" ) );
WPRINT_WICED_INFO( ("\r\n") );
#endif /* SCAN_TO_GET_SECURITY */
/* Store AP credentials into DCT */
WPRINT_WICED_INFO( ("Storing received credentials in DCT\r\n") );
wiced_dct_read_lock( (void**) &dct_ap_entry, WICED_TRUE, DCT_WIFI_CONFIG_SECTION, offsetof(platform_dct_wifi_config_t, stored_ap_list), sizeof(wiced_config_ap_entry_t) );
/* Setup the AP details */
dct_ap_entry->details.security = ws->security;
dct_ap_entry->details.channel = ws->channel;
dct_ap_entry->details.band = WICED_802_11_BAND_2_4GHZ;
dct_ap_entry->details.bss_type = WICED_BSS_TYPE_INFRASTRUCTURE;
memcpy(&dct_ap_entry->details.SSID, &result->ap_ssid, sizeof(wiced_ssid_t));
memcpy(dct_ap_entry->details.BSSID.octet, result->ap_bssid.octet, sizeof(wiced_mac_t));
/* Store the AP security into DCT */
if (ws->security == WICED_SECURITY_WPA_TKIP_PSK ||
ws->security == WICED_SECURITY_WPA_AES_PSK ||
ws->security == WICED_SECURITY_WPA2_AES_PSK ||
ws->security == WICED_SECURITY_WPA2_TKIP_PSK ||
ws->security == WICED_SECURITY_WPA2_MIXED_PSK )
{
dct_ap_entry->security_key_length = result->security_key_length;
memset(dct_ap_entry->security_key, 0, 64);
memcpy(dct_ap_entry->security_key, result->security_key, 64);
}
else if ( ws->security == WICED_SECURITY_WEP_PSK ||
ws->security == WICED_SECURITY_WEP_SHARED )
{
uint8_t wep_key_buffer[64];
wiced_wep_key_t* temp_wep_key = (wiced_wep_key_t*)wep_key_buffer;
uint8_t* security_key;
uint8_t key_length;
char temp_string[3];
int a;
temp_string[2] = 0;
key_length = result->security_key_length;
if ( key_length == 5 || key_length == 13 || key_length == 16 )
{
/* Setup WEP key 0 */
temp_wep_key[0].index = 0;
temp_wep_key[0].length = key_length;
memcpy(temp_wep_key[0].data, result->security_key, key_length);
}
else if ( key_length == 10 || key_length == 26 || key_length == 32 )
{
key_length = key_length/2;
/* Setup WEP key 0 */
temp_wep_key[0].index = 0;
temp_wep_key[0].length = key_length;
for ( a = 0; a < temp_wep_key[0].length; ++a )
{
memcpy(temp_string, &result->security_key[a*2], 2);
temp_wep_key[0].data[a] = (uint8_t)hex_str_to_int(temp_string);
}
}
else
{
WPRINT_APP_INFO(( "Invalid wep key length\r\n" ));
return WWD_INVALID_KEY;
}
/* Setup WEP keys 1 to 3 */
memcpy(wep_key_buffer + 1*(2 + key_length), temp_wep_key, (uint8_t)(2 + key_length));
memcpy(wep_key_buffer + 2*(2 + key_length), temp_wep_key, (uint8_t)(2 + key_length));
memcpy(wep_key_buffer + 3*(2 + key_length), temp_wep_key, (uint8_t)(2 + key_length));
wep_key_buffer[1*(2 + key_length)] = 1;
wep_key_buffer[2*(2 + key_length)] = 2;
wep_key_buffer[3*(2 + key_length)] = 3;
security_key = wep_key_buffer;
key_length = (uint8_t)(4*(2 + key_length));
dct_ap_entry->security_key_length = key_length;
memcpy(dct_ap_entry->security_key, security_key, 64);
}
#ifndef AUTO_TEST
/* Call API to store into DCT */
wiced_dct_write( dct_ap_entry, DCT_WIFI_CONFIG_SECTION, offsetof(platform_dct_wifi_config_t, stored_ap_list), sizeof(wiced_config_ap_entry_t) );
#endif
free( ws );
ws = NULL;
return WWD_SUCCESS;
}
int easy_setup_get_protocol(uint8_t* protocol) {
*protocol = g_protocol;
return 0;
}