修复mico-sdk错误

This commit is contained in:
nhkefus
2025-03-11 15:54:45 +08:00
parent 3422912129
commit 2ccb892a1c
2152 changed files with 664341 additions and 702636 deletions

View File

@@ -1,70 +1,70 @@
/**
******************************************************************************
* @file MFi_WAC.h
* @author William Xu
* @version V1.0.0
* @date 05-May-2014
* @brief This file provide header file for start a Apple WAC (wireless accessory
* configuration) function thread.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#pragma once
#include "mico.h"
#ifdef __cplusplus
extern "C" {
#endif
#define BUNDLE_SEED_ID "C6P64J2MZX"
#define EA_PROTOCOL "com.issc.datapath"
/**
* @brief Parameters controlled by the platform to configure the WAC process.
*/
typedef struct
{
uint8_t macAddress[ 6 ]; /**< REQUIRED: Accessory MAC address, e.g. 00:11:22:33:44:55. */
bool isUnconfigured; /**< TRUE/FALSE: whether the accessory is unconfigured. Should be true for current cases. */
bool supportsAirPlay; /**< TRUE/FALSE: whether the accessory supports AirPlay. */
bool supportsAirPrint; /**< TRUE/FALSE: whether the accessory supports AirPrint. */
bool supports2_4GHzWiFi; /**< TRUE/FALSE: whether the accessory supports 2.4 GHz Wi-Fi. */
bool supports5GHzWiFi; /**< TRUE/FALSE: whether the accessory supports 5 GHz Wi-Fi. */
bool supportsWakeOnWireless; /**< TRUE/FALSE: whether the accessory supports Wake On Wireless. */
char *firmwareRevision; /**< REQUIRED: Version of the accessory's firmware, e.g. 1.0.0. */
char *hardwareRevision; /**< REQUIRED: Version of the accessory's hardware, e.g. 1.0.0. */
char *serialNumber; /**< OPTIONAL: Accessory's serial number. */
char *name; /**< REQUIRED: Name of the accessory. */
char *model; /**< REQUIRED: Model name of the accessory. */
char *manufacturer; /**< REQUIRED: Manufacturer name of the accessory. */
char **eaProtocols; /**< OPTIONAL: Array of EA Protocol strings. */
uint8_t numEAProtocols; /**< OPTIONAL: Number of EA Protocol strings contained in the eaProtocols array. */
char *eaBundleSeedID; /**< OPTIONAL: Accessory manufacturer's BundleSeedID. */
} WACPlatformParameters_t;
void mfi_wac_lib_version( uint8_t *major, uint8_t *minor, uint8_t *revision );
OSStatus mfi_wac_start( mico_Context_t * const inContext, WACPlatformParameters_t *inWACPara, mico_i2c_t i2c, int timeOut );
OSStatus mfi_wac_stop( void );
#ifdef __cplusplus
} /*extern "C" */
#endif
/**
******************************************************************************
* @file MFi_WAC.h
* @author William Xu
* @version V1.0.0
* @date 05-May-2014
* @brief This file provide header file for start a Apple WAC (wireless accessory
* configuration) function thread.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#pragma once
#include "mico.h"
#ifdef __cplusplus
extern "C" {
#endif
#define BUNDLE_SEED_ID "C6P64J2MZX"
#define EA_PROTOCOL "com.issc.datapath"
/**
* @brief Parameters controlled by the platform to configure the WAC process.
*/
typedef struct
{
uint8_t macAddress[ 6 ]; /**< REQUIRED: Accessory MAC address, e.g. 00:11:22:33:44:55. */
bool isUnconfigured; /**< TRUE/FALSE: whether the accessory is unconfigured. Should be true for current cases. */
bool supportsAirPlay; /**< TRUE/FALSE: whether the accessory supports AirPlay. */
bool supportsAirPrint; /**< TRUE/FALSE: whether the accessory supports AirPrint. */
bool supports2_4GHzWiFi; /**< TRUE/FALSE: whether the accessory supports 2.4 GHz Wi-Fi. */
bool supports5GHzWiFi; /**< TRUE/FALSE: whether the accessory supports 5 GHz Wi-Fi. */
bool supportsWakeOnWireless; /**< TRUE/FALSE: whether the accessory supports Wake On Wireless. */
char *firmwareRevision; /**< REQUIRED: Version of the accessory's firmware, e.g. 1.0.0. */
char *hardwareRevision; /**< REQUIRED: Version of the accessory's hardware, e.g. 1.0.0. */
char *serialNumber; /**< OPTIONAL: Accessory's serial number. */
char *name; /**< REQUIRED: Name of the accessory. */
char *model; /**< REQUIRED: Model name of the accessory. */
char *manufacturer; /**< REQUIRED: Manufacturer name of the accessory. */
char **eaProtocols; /**< OPTIONAL: Array of EA Protocol strings. */
uint8_t numEAProtocols; /**< OPTIONAL: Number of EA Protocol strings contained in the eaProtocols array. */
char *eaBundleSeedID; /**< OPTIONAL: Accessory manufacturer's BundleSeedID. */
} WACPlatformParameters_t;
void mfi_wac_lib_version( uint8_t *major, uint8_t *minor, uint8_t *revision );
OSStatus mfi_wac_start( mico_Context_t * const inContext, WACPlatformParameters_t *inWACPara, mico_i2c_t i2c, int timeOut );
OSStatus mfi_wac_stop( void );
#ifdef __cplusplus
} /*extern "C" */
#endif

View File

@@ -1,14 +1,14 @@
#
# Copyright 2016, MXCHIP Corporation
# All Rights Reserved.
#
MFi_WAC_DIR := src
$(NAME)_SOURCES += \
$(MFi_WAC_DIR)/MFi-SAP.c \
$(MFi_WAC_DIR)/MFiSAPServer.c \
$(MFi_WAC_DIR)/WAC.c
#
# Copyright 2016, MXCHIP Corporation
# All Rights Reserved.
#
MFi_WAC_DIR := src
$(NAME)_SOURCES += \
$(MFi_WAC_DIR)/MFi-SAP.c \
$(MFi_WAC_DIR)/MFiSAPServer.c \
$(MFi_WAC_DIR)/WAC.c

View File

@@ -1,20 +1,20 @@
#
# UNPUBLISHED PROPRIETARY SOURCE CODE
# Copyright (c) 2016 MXCHIP Inc.
#
# The contents of this file may not be disclosed to third parties, copied or
# duplicated in any form, in whole or in part, without the prior written
# permission of MXCHIP Corporation.
#
NAME := Lib_MiCO_System_WAC
ifneq ($(wildcard $(CURDIR)Lib_MFi_WAC.$(HOST_ARCH).$(TOOLCHAIN_NAME).release.a),)
$(NAME)_PREBUILT_LIBRARY := Lib_MFi_WAC.$(HOST_ARCH).$(TOOLCHAIN_NAME).release.a
else
# Build from source
include $(CURDIR)Lib_MFi_WAC_src.mk
endif
$(NAME)_COMPONENTS += drivers/MiCODriverMFiAuth
#
# UNPUBLISHED PROPRIETARY SOURCE CODE
# Copyright (c) 2016 MXCHIP Inc.
#
# The contents of this file may not be disclosed to third parties, copied or
# duplicated in any form, in whole or in part, without the prior written
# permission of MXCHIP Corporation.
#
NAME := Lib_MiCO_System_WAC
ifneq ($(wildcard $(CURDIR)Lib_MFi_WAC.$(HOST_ARCH).$(TOOLCHAIN_NAME).release.a),)
$(NAME)_PREBUILT_LIBRARY := Lib_MFi_WAC.$(HOST_ARCH).$(TOOLCHAIN_NAME).release.a
else
# Build from source
include $(CURDIR)Lib_MFi_WAC_src.mk
endif
$(NAME)_COMPONENTS += drivers/MiCODriverMFiAuth

View File

@@ -1,175 +1,175 @@
/**
******************************************************************************
* @file system_easylink.c
* @author William Xu
* @version V1.0.0
* @date 20-July-2015
* @brief This file provide the easylink function for quick provisioning and
* first time configuration.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "StringUtils.h"
#include "system_internal.h"
static void _bonjour_generate_txt_record( char *txt_record, uint32_t easyLink_id, WiFi_Interface interface,
system_context_t * const inContext )
{
char *temp_txt2 = NULL;
temp_txt2 = __strdup_trans_dot( FIRMWARE_REVISION );
sprintf( txt_record, "FW=%s.", temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( HARDWARE_REVISION );
sprintf( txt_record, "%sHD=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( PROTOCOL );
sprintf( txt_record, "%sPO=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( inContext->micoStatus.rf_version );
sprintf( txt_record, "%sRF=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( inContext->micoStatus.mac );
sprintf( txt_record, "%sMAC=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( MicoGetVer( ) );
sprintf( txt_record, "%sOS=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( MODEL );
sprintf( txt_record, "%sMD=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( MANUFACTURER );
sprintf( txt_record, "%sMF=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
if ( interface == Soft_AP )
{
sprintf( txt_record, "%swlan unconfigured=T.", txt_record );
sprintf( txt_record, "%sFTC=T.", txt_record );
}
else
{
sprintf( txt_record, "%swlan unconfigured=F.", txt_record );
#ifdef MICO_CONFIG_SERVER_ENABLE
sprintf(txt_record, "%sFTC=T.", txt_record);
#else
sprintf( txt_record, "%sFTC=F.", txt_record );
#endif
}
sprintf( txt_record, "%sID=%lx.", txt_record, easyLink_id );
}
OSStatus easylink_bonjour_start( WiFi_Interface interface, uint32_t easyLink_id, system_context_t * const inContext )
{
char *temp_txt = NULL;
OSStatus err = kNoErr;
net_para_st para;
mdns_init_t init;
temp_txt = malloc( 500 );
require_action( temp_txt, exit, err = kNoMemoryErr );
memset( &init, 0x0, sizeof(mdns_init_t) );
micoWlanGetIPStatus( &para, interface );
init.service_name = "_easylink_config._tcp.local.";
/* name(xxxxxx).local. */
snprintf( temp_txt, 100, "%s(%c%c%c%c%c%c).local.", MODEL,
inContext->micoStatus.mac[9],
inContext->micoStatus.mac[10],
inContext->micoStatus.mac[12],
inContext->micoStatus.mac[13],
inContext->micoStatus.mac[15],
inContext->micoStatus.mac[16] );
init.host_name = (char*) __strdup( temp_txt );
/* name(xxxxxx). */
snprintf( temp_txt, 100, "%s(%c%c%c%c%c%c)", MODEL,
inContext->micoStatus.mac[9],
inContext->micoStatus.mac[10],
inContext->micoStatus.mac[12],
inContext->micoStatus.mac[13],
inContext->micoStatus.mac[15],
inContext->micoStatus.mac[16] );
init.instance_name = (char*) __strdup( temp_txt );
init.service_port = MICO_CONFIG_SERVER_PORT;
_bonjour_generate_txt_record( temp_txt, easyLink_id, interface, inContext );
init.txt_record = (char*) __strdup( temp_txt );
if ( interface == Soft_AP )
mdns_add_record( init, interface, 1500 );
else
mdns_add_record( init, interface, 10 );
free( init.host_name );
free( init.instance_name );
free( init.txt_record );
exit:
if ( temp_txt ) free( temp_txt );
return err;
}
OSStatus easylink_bonjour_update( WiFi_Interface interface, uint32_t easyLink_id, system_context_t * const inContext )
{
char *temp_txt = NULL;
OSStatus err = kNoErr;
temp_txt = malloc( 500 );
require_action( temp_txt, exit, err = kNoMemoryErr );
_bonjour_generate_txt_record( temp_txt, easyLink_id, interface, inContext );
mdns_update_txt_record( "_easylink_config._tcp.local.", interface, temp_txt );
exit:
if ( temp_txt ) free( temp_txt );
return err;
}
void easylink_remove_bonjour( void )
{
mdns_record_state_t easylink_service_state = RECORD_REMOVED;
/* Remove previous _easylink_config service if existed */
easylink_service_state = mdns_get_record_status( "_easylink_config._tcp.local.", Station);
if ( easylink_service_state != RECORD_REMOVED )
{
UnSetTimer( easylink_remove_bonjour );
mdns_suspend_record( "_easylink_config._tcp.local.", Station, true );
mico_rtos_delay_milliseconds( 1500 );
}
/* Remove previous _easylink_config service if existed */
easylink_service_state = mdns_get_record_status( "_easylink_config._tcp.local.", Soft_AP);
if ( easylink_service_state != RECORD_REMOVED )
{
mdns_suspend_record( "_easylink_config._tcp.local.", Soft_AP, true );
mico_rtos_delay_milliseconds( 1500 );
}
}
/**
******************************************************************************
* @file system_easylink.c
* @author William Xu
* @version V1.0.0
* @date 20-July-2015
* @brief This file provide the easylink function for quick provisioning and
* first time configuration.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "StringUtils.h"
#include "system_internal.h"
static void _bonjour_generate_txt_record( char *txt_record, uint32_t easyLink_id, WiFi_Interface interface,
system_context_t * const inContext )
{
char *temp_txt2 = NULL;
temp_txt2 = __strdup_trans_dot( FIRMWARE_REVISION );
sprintf( txt_record, "FW=%s.", temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( HARDWARE_REVISION );
sprintf( txt_record, "%sHD=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( PROTOCOL );
sprintf( txt_record, "%sPO=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( inContext->micoStatus.rf_version );
sprintf( txt_record, "%sRF=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( inContext->micoStatus.mac );
sprintf( txt_record, "%sMAC=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( MicoGetVer( ) );
sprintf( txt_record, "%sOS=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( MODEL );
sprintf( txt_record, "%sMD=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
temp_txt2 = __strdup_trans_dot( MANUFACTURER );
sprintf( txt_record, "%sMF=%s.", txt_record, temp_txt2 );
free( temp_txt2 );
if ( interface == Soft_AP )
{
sprintf( txt_record, "%swlan unconfigured=T.", txt_record );
sprintf( txt_record, "%sFTC=T.", txt_record );
}
else
{
sprintf( txt_record, "%swlan unconfigured=F.", txt_record );
#ifdef MICO_CONFIG_SERVER_ENABLE
sprintf(txt_record, "%sFTC=T.", txt_record);
#else
sprintf( txt_record, "%sFTC=F.", txt_record );
#endif
}
sprintf( txt_record, "%sID=%lx.", txt_record, easyLink_id );
}
OSStatus easylink_bonjour_start( WiFi_Interface interface, uint32_t easyLink_id, system_context_t * const inContext )
{
char *temp_txt = NULL;
OSStatus err = kNoErr;
net_para_st para;
mdns_init_t init;
temp_txt = malloc( 500 );
require_action( temp_txt, exit, err = kNoMemoryErr );
memset( &init, 0x0, sizeof(mdns_init_t) );
micoWlanGetIPStatus( &para, interface );
init.service_name = "_easylink_config._tcp.local.";
/* name(xxxxxx).local. */
snprintf( temp_txt, 100, "%s(%c%c%c%c%c%c).local.", MODEL,
inContext->micoStatus.mac[9],
inContext->micoStatus.mac[10],
inContext->micoStatus.mac[12],
inContext->micoStatus.mac[13],
inContext->micoStatus.mac[15],
inContext->micoStatus.mac[16] );
init.host_name = (char*) __strdup( temp_txt );
/* name(xxxxxx). */
snprintf( temp_txt, 100, "%s(%c%c%c%c%c%c)", MODEL,
inContext->micoStatus.mac[9],
inContext->micoStatus.mac[10],
inContext->micoStatus.mac[12],
inContext->micoStatus.mac[13],
inContext->micoStatus.mac[15],
inContext->micoStatus.mac[16] );
init.instance_name = (char*) __strdup( temp_txt );
init.service_port = MICO_CONFIG_SERVER_PORT;
_bonjour_generate_txt_record( temp_txt, easyLink_id, interface, inContext );
init.txt_record = (char*) __strdup( temp_txt );
if ( interface == Soft_AP )
mdns_add_record( init, interface, 1500 );
else
mdns_add_record( init, interface, 10 );
free( init.host_name );
free( init.instance_name );
free( init.txt_record );
exit:
if ( temp_txt ) free( temp_txt );
return err;
}
OSStatus easylink_bonjour_update( WiFi_Interface interface, uint32_t easyLink_id, system_context_t * const inContext )
{
char *temp_txt = NULL;
OSStatus err = kNoErr;
temp_txt = malloc( 500 );
require_action( temp_txt, exit, err = kNoMemoryErr );
_bonjour_generate_txt_record( temp_txt, easyLink_id, interface, inContext );
mdns_update_txt_record( "_easylink_config._tcp.local.", interface, temp_txt );
exit:
if ( temp_txt ) free( temp_txt );
return err;
}
void easylink_remove_bonjour( void )
{
mdns_record_state_t easylink_service_state = RECORD_REMOVED;
/* Remove previous _easylink_config service if existed */
easylink_service_state = mdns_get_record_status( "_easylink_config._tcp.local.", Station);
if ( easylink_service_state != RECORD_REMOVED )
{
UnSetTimer( easylink_remove_bonjour );
mdns_suspend_record( "_easylink_config._tcp.local.", Station, true );
mico_rtos_delay_milliseconds( 1500 );
}
/* Remove previous _easylink_config service if existed */
easylink_service_state = mdns_get_record_status( "_easylink_config._tcp.local.", Soft_AP);
if ( easylink_service_state != RECORD_REMOVED )
{
mdns_suspend_record( "_easylink_config._tcp.local.", Soft_AP, true );
mico_rtos_delay_milliseconds( 1500 );
}
}

View File

@@ -1,44 +1,44 @@
/**
******************************************************************************
* @file airkiss_discovery.h
* @author William Xu
* @version V1.0.0
* @date 28-10-2015
* @brief Head file for WECHAT device discovery protocol
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#ifndef __EASYLINK_INTERNAL_H
#define __EASYLINK_INTERNAL_H
#include "mico.h"
#include "system_internal.h"
#ifdef __cplusplus
extern "C" {
#endif
OSStatus easylink_bonjour_start( WiFi_Interface interface, uint32_t easyLink_id, system_context_t * const inContext );
OSStatus easylink_bonjour_update( WiFi_Interface interface, uint32_t easyLink_id, system_context_t * const inContext );
void easylink_remove_bonjour( void );
OSStatus easylink_softap_start( system_context_t * const inContext );
uint32_t easylink_softap_get_identifier( void );
#ifdef __cplusplus
} /*extern "C" */
#endif
#endif //__EASYLINK_INTERNAL_H
/**
******************************************************************************
* @file airkiss_discovery.h
* @author William Xu
* @version V1.0.0
* @date 28-10-2015
* @brief Head file for WECHAT device discovery protocol
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#ifndef __EASYLINK_INTERNAL_H
#define __EASYLINK_INTERNAL_H
#include "mico.h"
#include "system_internal.h"
#ifdef __cplusplus
extern "C" {
#endif
OSStatus easylink_bonjour_start( WiFi_Interface interface, uint32_t easyLink_id, system_context_t * const inContext );
OSStatus easylink_bonjour_update( WiFi_Interface interface, uint32_t easyLink_id, system_context_t * const inContext );
void easylink_remove_bonjour( void );
OSStatus easylink_softap_start( system_context_t * const inContext );
uint32_t easylink_softap_get_identifier( void );
#ifdef __cplusplus
} /*extern "C" */
#endif
#endif //__EASYLINK_INTERNAL_H

View File

@@ -1,304 +1,334 @@
/**
******************************************************************************
* @file system_easylink.c
* @author William Xu
* @version V1.0.0
* @date 20-July-2015
* @brief This file provide the easylink function for quick provisioning and
* first time configuration.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "system_internal.h"
#include "easylink_internal.h"
#include "StringUtils.h"
//#if (MICO_WLAN_CONFIG_MODE == CONFIG_MODE_EASYLINK) || (MICO_WLAN_CONFIG_MODE == CONFIG_MODE_EASYLINK_WITH_SOFTAP)
/******************************************************
* Function Declarations
******************************************************/
/* EasyLink event callback functions*/
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext );
static void easylink_complete_cb( network_InitTypeDef_st *nwkpara, system_context_t * const inContext );
static void easylink_extra_data_cb( int datalen, char* data, system_context_t * const inContext );
/* Thread perform easylink and connect to wlan */
static void easylink_thread( uint32_t inContext ); /* Perform easylink and connect to wlan */
/******************************************************
* Variables Definitions
******************************************************/
static mico_semaphore_t easylink_sem; /**< Used to suspend thread while easylink. */
static mico_semaphore_t easylink_connect_sem; /**< Used to suspend thread while connection. */
static bool easylink_success = false; /**< true: connect to wlan, false: start soft ap mode or roll back to previous settings */
static uint32_t easylinkIndentifier = 0; /**< Unique for an easylink instance. */
static mico_thread_t easylink_thread_handler = NULL;
static bool easylink_thread_force_exit = false;
static mico_config_source_t source = CONFIG_BY_NONE;
/******************************************************
* Function Definitions
******************************************************/
/* MiCO callback when WiFi status is changed */
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext )
{
switch ( event )
{
case NOTIFY_STATION_UP:
/* Connected to AP, means that the wlan configuration is right, update configuration in flash and update
bongjour txt record with new "easylinkIndentifier" */
easylink_bonjour_update( Station, easylinkIndentifier, inContext );
inContext->flashContentInRam.micoSystemConfig.configured = allConfigured;
mico_system_context_update( &inContext->flashContentInRam ); //Update Flash content
mico_rtos_set_semaphore( &easylink_connect_sem ); //Notify Easylink thread
break;
default:
break;
}
return;
}
/* MiCO callback when EasyLink is finished step 1, return SSID and KEY */
static void easylink_complete_cb( network_InitTypeDef_st *nwkpara, system_context_t * const inContext )
{
OSStatus err = kNoErr;
require_action_string( nwkpara, exit, err = kTimeoutErr, "EasyLink Timeout or terminated" );
/* Store SSID and KEY*/
mico_rtos_lock_mutex( &inContext->flashContentInRam_mutex );
memcpy( inContext->flashContentInRam.micoSystemConfig.ssid, nwkpara->wifi_ssid, maxSsidLen );
memset( inContext->flashContentInRam.micoSystemConfig.bssid, 0x0, 6 );
memcpy( inContext->flashContentInRam.micoSystemConfig.user_key, nwkpara->wifi_key, maxKeyLen );
inContext->flashContentInRam.micoSystemConfig.user_keyLength = strlen( nwkpara->wifi_key );
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = true;
mico_rtos_unlock_mutex( &inContext->flashContentInRam_mutex );
system_log("Get SSID: %s, Key: %s", inContext->flashContentInRam.micoSystemConfig.ssid, inContext->flashContentInRam.micoSystemConfig.user_key);
source = (mico_config_source_t) nwkpara->wifi_retry_interval;
exit:
if ( err != kNoErr )
{
/*EasyLink timeout or error*/
easylink_success = false;
mico_rtos_set_semaphore( &easylink_sem );
}
return;
}
/* MiCO callback when EasyLink is finished step 2, return extra data
data format: [AuthData#Identifier]<localIp/netMask/gateWay/dnsServer>
Auth data: Provide to application, application will decide if this is a proter configuration for currnet device
Identifier: Unique id for every easylink instance send by easylink mobile app
localIp/netMask/gateWay/dnsServer: Device static ip address, use DHCP if not exist
*/
static void easylink_extra_data_cb( int datalen, char* data, system_context_t * const inContext )
{
OSStatus err = kNoErr;
int index;
uint32_t *identifier, ipInfoCount;
char *debugString;
struct in_addr ipv4_addr;
debugString = DataToHexStringWithSpaces( (const uint8_t *) data, datalen );
system_log("Get user info: %s", debugString);
free( debugString );
/* Find '#' that separate authdata and identifier*/
for ( index = datalen - 1; index >= 0; index-- )
{
if ( data[index] == '#' && ((datalen - index) == 5 || (datalen - index) == 25) )
break;
}
require_action( index >= 0, exit, err = kParamErr );
/* Check auth data by device */
data[index++] = 0x0;
err = mico_system_delegate_config_recv_auth_data( data );
require_noerr( err, exit );
/* Read identifier */
identifier = (uint32_t *) &data[index];
easylinkIndentifier = *identifier;
/* Identifier: 1 x uint32_t or Identifier/localIp/netMask/gateWay/dnsServer: 5 x uint32_t */
ipInfoCount = (datalen - index) / sizeof(uint32_t);
require_action( ipInfoCount >= 1, exit, err = kParamErr );
mico_rtos_lock_mutex( &inContext->flashContentInRam_mutex );
if ( ipInfoCount == 1 )
{ //Use DHCP to obtain local ip address
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = true;
system_log("Get auth info: %s, EasyLink identifier: %lx", data, easylinkIndentifier);
} else
{ //Use static ip address
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = false;
ipv4_addr.s_addr = *(identifier+1);
strcpy( (char *) inContext->micoStatus.localIp, inet_ntoa( ipv4_addr ) );
ipv4_addr.s_addr = *(identifier+2);
strcpy( (char *) inContext->micoStatus.netMask, inet_ntoa( ipv4_addr ) );
ipv4_addr.s_addr = *(identifier+3);
strcpy( (char *) inContext->micoStatus.gateWay, inet_ntoa( ipv4_addr ) );
ipv4_addr.s_addr = *(identifier+4);
strcpy( (char *) inContext->micoStatus.dnsServer, inet_ntoa( ipv4_addr ) );
system_log("Get auth info: %s, EasyLink identifier: %lx, local IP info:%s %s %s %s ", data, easylinkIndentifier, inContext->flashContentInRam.micoSystemConfig.localIp,
inContext->flashContentInRam.micoSystemConfig.netMask, inContext->flashContentInRam.micoSystemConfig.gateWay,inContext->flashContentInRam.micoSystemConfig.dnsServer);
}
mico_rtos_unlock_mutex( &inContext->flashContentInRam_mutex );
source = CONFIG_BY_EASYLINK_V2;
exit:
if ( err != kNoErr )
{
/*EasyLink error*/
system_log("EasyLink step 2 ERROR, err: %d", err);
easylink_success = false;
} else
/* Easylink success after step 1 and step 2 */
easylink_success = true;
mico_rtos_set_semaphore( &easylink_sem );
return;
}
static void easylink_thread( uint32_t arg )
{
OSStatus err = kNoErr;
system_context_t *context = (system_context_t *) arg;
easylinkIndentifier = 0x0;
easylink_success = false;
easylink_thread_force_exit = false;
source = CONFIG_BY_NONE;
mico_system_notify_register( mico_notify_EASYLINK_WPS_COMPLETED, (void *) easylink_complete_cb, context );
mico_system_notify_register( mico_notify_EASYLINK_GET_EXTRA_DATA, (void *) easylink_extra_data_cb, context );
mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void *) easylink_wifi_status_cb, context );
mico_rtos_init_semaphore( &easylink_sem, 1 );
mico_rtos_init_semaphore( &easylink_connect_sem, 1 );
restart:
mico_system_delegate_config_will_start( );
system_log("Start easylink combo mode");
micoWlanStartEasyLinkPlus( EasyLink_TimeOut / 1000 );
while( mico_rtos_get_semaphore( &easylink_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_sem, MICO_WAIT_FOREVER );
/* Easylink force exit by user, clean and exit */
if( err != kNoErr && easylink_thread_force_exit )
{
system_log("EasyLink waiting for terminate");
micoWlanStopEasyLinkPlus( );
mico_rtos_get_semaphore( &easylink_sem, 3000 );
system_log("EasyLink canceled by user");
goto exit;
}
/* EasyLink Success */
if ( easylink_success == true )
{
mico_system_delegate_config_recv_ssid( context->flashContentInRam.micoSystemConfig.ssid,
context->flashContentInRam.micoSystemConfig.user_key );
system_connect_wifi_normal( context );
/* Wait for station connection */
while( mico_rtos_get_semaphore( &easylink_connect_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_connect_sem, EasyLink_ConnectWlan_Timeout );
/* Easylink force exit by user, clean and exit */
if( err != kNoErr && easylink_thread_force_exit )
{
micoWlanSuspend();
system_log("EasyLink connection canceled by user");
goto exit;
}
/*SSID or Password is not correct, module cannot connect to wlan, so restart EasyLink again*/
require_noerr_action_string( err, restart, micoWlanSuspend(), "Re-start easylink combo mode" );
mico_system_delegate_config_success( source );
/* Start bonjour service for new device discovery */
err = easylink_bonjour_start( Station, easylinkIndentifier, context );
require_noerr( err, exit );
SetTimer( 60 * 1000, easylink_remove_bonjour );
goto exit;
}
else /* EasyLink failed */
{
/* so roll back to previous settings (if it has) and connect */
if ( context->flashContentInRam.micoSystemConfig.configured != unConfigured ) {
system_log("Roll back to previous settings");
MICOReadConfiguration( context );
system_connect_wifi_normal( context );
}
else {
/*module should power down in default setting*/
system_log("Wi-Fi power off");
micoWlanPowerOff();
}
}
exit:
easylink_thread_force_exit = false;
mico_system_delegate_config_will_stop( );
mico_system_notify_remove( mico_notify_WIFI_STATUS_CHANGED, (void *)easylink_wifi_status_cb );
mico_system_notify_remove( mico_notify_EASYLINK_WPS_COMPLETED, (void *)easylink_complete_cb );
mico_system_notify_remove( mico_notify_EASYLINK_GET_EXTRA_DATA, (void *)easylink_extra_data_cb );
mico_rtos_deinit_semaphore( &easylink_sem );
mico_rtos_deinit_semaphore( &easylink_connect_sem );
easylink_thread_handler = NULL;
mico_rtos_delete_thread( NULL );
}
OSStatus mico_easylink( mico_Context_t * const in_context, mico_bool_t enable )
{
OSStatus err = kUnknownErr;
require_action( in_context, exit, err = kNotPreparedErr );
easylink_remove_bonjour( );
/* easylink thread existed? stop! */
if ( easylink_thread_handler ) {
system_log("EasyLink processing, force stop..");
easylink_thread_force_exit = true;
mico_rtos_thread_force_awake( &easylink_thread_handler );
mico_rtos_thread_join( &easylink_thread_handler );
}
if ( enable == MICO_TRUE ) {
err = mico_rtos_create_thread( &easylink_thread_handler, MICO_APPLICATION_PRIORITY, "EASYLINK", easylink_thread,
0x1000, (mico_thread_arg_t) in_context );
require_noerr_string( err, exit, "ERROR: Unable to start the EasyLink thread." );
/* Make sure easylink is already running, and waiting for sem trigger */
mico_rtos_delay_milliseconds( 100 );
}
exit:
return err;
}
//#endif
/**
******************************************************************************
* @file system_easylink.c
* @author William Xu
* @version V1.0.0
* @date 20-July-2015
* @brief This file provide the easylink function for quick provisioning and
* first time configuration.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "system_internal.h"
#include "easylink_internal.h"
#include "StringUtils.h"
//#if (MICO_WLAN_CONFIG_MODE == CONFIG_MODE_EASYLINK) || (MICO_WLAN_CONFIG_MODE == CONFIG_MODE_EASYLINK_WITH_SOFTAP)
/******************************************************
* Function Declarations
******************************************************/
/* EasyLink event callback functions*/
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext );
static void easylink_complete_cb( network_InitTypeDef_st *nwkpara, system_context_t * const inContext );
static void easylink_extra_data_cb( int datalen, char* data, system_context_t * const inContext );
/* Thread perform easylink and connect to wlan */
static void easylink_thread( uint32_t inContext ); /* Perform easylink and connect to wlan */
/******************************************************
* Variables Definitions
******************************************************/
static mico_semaphore_t easylink_sem; /**< Used to suspend thread while easylink. */
static mico_semaphore_t easylink_connect_sem; /**< Used to suspend thread while connection. */
static bool easylink_success = false; /**< true: connect to wlan, false: start soft ap mode or roll back to previous settings */
static uint32_t easylinkIndentifier = 0; /**< Unique for an easylink instance. */
static mico_thread_t easylink_thread_handler = NULL;
static bool easylink_thread_force_exit = false;
static mico_config_source_t source = CONFIG_BY_NONE;
static bool easylink_with_softap = false;
/******************************************************
* Function Definitions
******************************************************/
/* MiCO callback when WiFi status is changed */
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext )
{
switch ( event )
{
case NOTIFY_STATION_UP:
/* Connected to AP, means that the wlan configuration is right, update configuration in flash and update
bongjour txt record with new "easylinkIndentifier" */
easylink_bonjour_update( Station, easylinkIndentifier, inContext );
inContext->flashContentInRam.micoSystemConfig.configured = allConfigured;
mico_system_context_update( &inContext->flashContentInRam ); //Update Flash content
mico_rtos_set_semaphore( &easylink_connect_sem ); //Notify Easylink thread
break;
default:
break;
}
return;
}
/* MiCO callback when EasyLink is finished step 1, return SSID and KEY */
static void easylink_complete_cb( network_InitTypeDef_st *nwkpara, system_context_t * const inContext )
{
OSStatus err = kNoErr;
require_action_string( nwkpara, exit, err = kTimeoutErr, "EasyLink Timeout or terminated" );
/* Store SSID and KEY*/
mico_rtos_lock_mutex( &inContext->flashContentInRam_mutex );
memcpy( inContext->flashContentInRam.micoSystemConfig.ssid, nwkpara->wifi_ssid, maxSsidLen );
memset( inContext->flashContentInRam.micoSystemConfig.bssid, 0x0, 6 );
memcpy( inContext->flashContentInRam.micoSystemConfig.user_key, nwkpara->wifi_key, maxKeyLen );
inContext->flashContentInRam.micoSystemConfig.user_keyLength = strlen( nwkpara->wifi_key );
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = true;
mico_rtos_unlock_mutex( &inContext->flashContentInRam_mutex );
system_log("Get SSID: %s, Key: %s", inContext->flashContentInRam.micoSystemConfig.ssid, inContext->flashContentInRam.micoSystemConfig.user_key);
source = (mico_config_source_t) nwkpara->wifi_retry_interval;
exit:
if ( err != kNoErr )
{
/*EasyLink timeout or error*/
easylink_success = false;
mico_rtos_set_semaphore( &easylink_sem );
}
return;
}
#ifdef MICO_EASYLINK_AND_SOFTAP_ENABLED
void easylink_uap_success(uint32_t id)
{
if (easylink_with_softap == false)
return;
system_log("sofapt configured");
easylinkIndentifier = id;
easylink_success = true;
micoWlanSuspendSoftAP();
mico_rtos_set_semaphore( &easylink_sem );
}
#endif
/* MiCO callback when EasyLink is finished step 2, return extra data
data format: [AuthData#Identifier]<localIp/netMask/gateWay/dnsServer>
Auth data: Provide to application, application will decide if this is a proter configuration for currnet device
Identifier: Unique id for every easylink instance send by easylink mobile app
localIp/netMask/gateWay/dnsServer: Device static ip address, use DHCP if not exist
*/
static void easylink_extra_data_cb( int datalen, char* data, system_context_t * const inContext )
{
OSStatus err = kNoErr;
int index;
uint32_t ipInfoCount;
char *debugString;
struct in_addr ipv4_addr;
debugString = DataToHexStringWithSpaces( (const uint8_t *) data, datalen );
system_log("Get user info: %s", debugString);
free( debugString );
/* Find '#' that separate authdata and identifier*/
for ( index = datalen - 1; index >= 0; index-- )
{
if ( data[index] == '#' && ((datalen - index) == 5 || (datalen - index) == 25) )
break;
}
require_action( index >= 0, exit, err = kParamErr );
/* Check auth data by device */
data[index++] = 0x0;
err = mico_system_delegate_config_recv_auth_data( data );
require_noerr( err, exit );
/* Read identifier */
memcpy(&easylinkIndentifier, &data[index], 4);
/* Identifier: 1 x uint32_t or Identifier/localIp/netMask/gateWay/dnsServer: 5 x uint32_t */
ipInfoCount = (datalen - index) / sizeof(uint32_t);
require_action( ipInfoCount >= 1, exit, err = kParamErr );
mico_rtos_lock_mutex( &inContext->flashContentInRam_mutex );
if ( ipInfoCount == 1 )
{ //Use DHCP to obtain local ip address
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = true;
system_log("Get auth info: %s, EasyLink identifier: %lx", data, easylinkIndentifier);
} else
{ //Use static ip address
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = false;
memcpy(&ipv4_addr.s_addr, &data[index+4], 4);
strcpy( (char *) inContext->micoStatus.localIp, inet_ntoa( ipv4_addr ) );
memcpy(&ipv4_addr.s_addr, &data[index+8], 4);
strcpy( (char *) inContext->micoStatus.netMask, inet_ntoa( ipv4_addr ) );
memcpy(&ipv4_addr.s_addr, &data[index+12], 4);
strcpy( (char *) inContext->micoStatus.gateWay, inet_ntoa( ipv4_addr ) );
memcpy(&ipv4_addr.s_addr, &data[index+16], 4);
strcpy( (char *) inContext->micoStatus.dnsServer, inet_ntoa( ipv4_addr ) );
system_log("Get auth info: %s, EasyLink identifier: %lx, local IP info:%s %s %s %s ", data, easylinkIndentifier, inContext->flashContentInRam.micoSystemConfig.localIp,
inContext->flashContentInRam.micoSystemConfig.netMask, inContext->flashContentInRam.micoSystemConfig.gateWay,inContext->flashContentInRam.micoSystemConfig.dnsServer);
}
mico_rtos_unlock_mutex( &inContext->flashContentInRam_mutex );
source = CONFIG_BY_EASYLINK_V2;
exit:
if ( err != kNoErr )
{
/*EasyLink error*/
system_log("EasyLink step 2 ERROR, err: %d", err);
easylink_success = false;
} else
/* Easylink success after step 1 and step 2 */
easylink_success = true;
mico_rtos_set_semaphore( &easylink_sem );
return;
}
static void easylink_thread( uint32_t arg )
{
OSStatus err = kNoErr;
system_context_t *context = (system_context_t *) arg;
easylinkIndentifier = 0x0;
easylink_success = false;
easylink_thread_force_exit = false;
source = CONFIG_BY_NONE;
mico_system_notify_register( mico_notify_EASYLINK_WPS_COMPLETED, (void *) easylink_complete_cb, context );
mico_system_notify_register( mico_notify_EASYLINK_GET_EXTRA_DATA, (void *) easylink_extra_data_cb, context );
mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void *) easylink_wifi_status_cb, context );
mico_rtos_init_semaphore( &easylink_sem, 1 );
mico_rtos_init_semaphore( &easylink_connect_sem, 1 );
restart:
mico_system_delegate_config_will_start( );
system_log("Start easylink combo mode");
#ifdef MICO_EASYLINK_AND_SOFTAP_ENABLED
if (easylink_with_softap == true) {
char wifi_ssid[32];
sprintf( wifi_ssid, "EasyLink_%c%c%c%c%c%c",
context->micoStatus.mac[9], context->micoStatus.mac[10], context->micoStatus.mac[12],
context->micoStatus.mac[13], context->micoStatus.mac[15], context->micoStatus.mac[16]);
system_log("Enable softap %s in easylink", wifi_ssid);
OpenEasylink_softap( EasyLink_TimeOut / 1000, wifi_ssid, NULL, 6 );
/* Start config server */
config_server_start( );
easylink_bonjour_start( Soft_AP, 0, context );
} else
#endif
micoWlanStartEasyLinkPlus( EasyLink_TimeOut / 1000 );
while( mico_rtos_get_semaphore( &easylink_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_sem, EasyLink_TimeOut );
/* Easylink force exit by user, clean and exit */
if( err != kNoErr && easylink_thread_force_exit )
{
system_log("EasyLink waiting for terminate");
micoWlanStopEasyLinkPlus( );
mico_rtos_get_semaphore( &easylink_sem, 3000 );
system_log("EasyLink canceled by user");
goto exit;
}
/* EasyLink Success */
if ( easylink_success == true )
{
mico_system_delegate_config_recv_ssid( context->flashContentInRam.micoSystemConfig.ssid,
context->flashContentInRam.micoSystemConfig.user_key );
system_connect_wifi_normal( context );
/* Wait for station connection */
while( mico_rtos_get_semaphore( &easylink_connect_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_connect_sem, EasyLink_ConnectWlan_Timeout );
/* Easylink force exit by user, clean and exit */
if( err != kNoErr && easylink_thread_force_exit )
{
micoWlanSuspend();
system_log("EasyLink connection canceled by user");
goto exit;
}
/*SSID or Password is not correct, module cannot connect to wlan, so restart EasyLink again*/
require_noerr_action_string( err, restart, micoWlanSuspend(), "Re-start easylink combo mode" );
mico_system_delegate_config_success( source );
/* Start bonjour service for new device discovery */
err = easylink_bonjour_start( Station, easylinkIndentifier, context );
require_noerr( err, exit );
SetTimer( 60 * 1000, easylink_remove_bonjour );
goto exit;
}
else /* EasyLink failed */
{
/* so roll back to previous settings (if it has) and connect */
if ( context->flashContentInRam.micoSystemConfig.configured != unConfigured ) {
system_log("Roll back to previous settings");
MICOReadConfiguration( context );
system_connect_wifi_normal( context );
}
else {
/*module should power down in default setting*/
system_log("Wi-Fi power off");
micoWlanPowerOff();
}
}
exit:
easylink_thread_force_exit = false;
mico_system_delegate_config_will_stop( );
mico_system_notify_remove( mico_notify_WIFI_STATUS_CHANGED, (void *)easylink_wifi_status_cb );
mico_system_notify_remove( mico_notify_EASYLINK_WPS_COMPLETED, (void *)easylink_complete_cb );
mico_system_notify_remove( mico_notify_EASYLINK_GET_EXTRA_DATA, (void *)easylink_extra_data_cb );
mico_rtos_deinit_semaphore( &easylink_sem );
mico_rtos_deinit_semaphore( &easylink_connect_sem );
easylink_thread_handler = NULL;
mico_rtos_delete_thread( NULL );
}
OSStatus mico_easylink( mico_Context_t * const in_context, mico_bool_t enable, mico_bool_t softap )
{
OSStatus err = kUnknownErr;
require_action( in_context, exit, err = kNotPreparedErr );
easylink_remove_bonjour( );
/* easylink thread existed? stop! */
if ( easylink_thread_handler ) {
system_log("EasyLink processing, force stop..");
easylink_thread_force_exit = true;
mico_rtos_thread_force_awake( &easylink_thread_handler );
mico_rtos_thread_join( &easylink_thread_handler );
}
if ( enable == MICO_TRUE ) {
if (softap == MICO_TRUE)
easylink_with_softap = true;
else
easylink_with_softap = false;
err = mico_rtos_create_thread( &easylink_thread_handler, MICO_APPLICATION_PRIORITY, "EASYLINK", easylink_thread,
0x1000, (mico_thread_arg_t) in_context );
require_noerr_string( err, exit, "ERROR: Unable to start the EasyLink thread." );
/* Make sure easylink is already running, and waiting for sem trigger */
mico_rtos_delay_milliseconds( 100 );
}
exit:
return err;
}
//#endif

View File

@@ -1,125 +1,152 @@
/**
******************************************************************************
* @file system_easylink_delegate.c
* @author William Xu
* @version V1.0.0
* @date 05-May-2014
* @brief This file provide delegate functions from Easylink.
******************************************************************************
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "platform_config.h"
#include "StringUtils.h"
#include "system.h"
#define SYS_LED_TRIGGER_INTERVAL 100
#define SYS_LED_TRIGGER_INTERVAL_AFTER_EASYLINK 500
static mico_timer_t _Led_EL_timer;
static bool _Led_EL_timer_initialized = false;
static void _led_EL_Timeout_handler( void* arg )
{
(void)(arg);
MicoGpioOutputTrigger((mico_gpio_t)MICO_SYS_LED);
}
WEAK void mico_system_delegate_config_will_start( void )
{
/*Led trigger*/
if(_Led_EL_timer_initialized == true)
{
mico_stop_timer(&_Led_EL_timer);
mico_deinit_timer( &_Led_EL_timer );
_Led_EL_timer_initialized = false;
}
mico_init_timer(&_Led_EL_timer, SYS_LED_TRIGGER_INTERVAL, _led_EL_Timeout_handler, NULL);
mico_start_timer(&_Led_EL_timer);
_Led_EL_timer_initialized = true;
return;
}
WEAK void mico_system_delegate_soft_ap_will_start( void )
{
return;
}
WEAK void mico_system_delegate_config_will_stop( void )
{
if(_Led_EL_timer_initialized == true)
{
mico_stop_timer(&_Led_EL_timer);
mico_deinit_timer( &_Led_EL_timer );
_Led_EL_timer_initialized = false;
}
MicoSysLed(true);
return;
}
WEAK void mico_system_delegate_config_recv_ssid ( char *ssid, char *key )
{
UNUSED_PARAMETER(ssid);
UNUSED_PARAMETER(key);
if(_Led_EL_timer_initialized == true)
{
mico_stop_timer(&_Led_EL_timer);
mico_deinit_timer( &_Led_EL_timer );
_Led_EL_timer_initialized = false;
}
mico_init_timer(&_Led_EL_timer, SYS_LED_TRIGGER_INTERVAL_AFTER_EASYLINK, _led_EL_Timeout_handler, NULL);
mico_start_timer(&_Led_EL_timer);
_Led_EL_timer_initialized = true;
return;
}
WEAK void mico_system_delegate_config_success( mico_config_source_t source )
{
//system_log( "Configed by %d", source );
UNUSED_PARAMETER(source);
return;
}
WEAK OSStatus mico_system_delegate_config_recv_auth_data(char * anthData )
{
(void)(anthData);
return kNoErr;
}
WEAK void mico_easylink_monitor_delegate_will_start( void )
{
}
WEAK void mico_easylink_monitor_delegate_stoped( void )
{
}
WEAK void mico_easylink_monitor_delegate_connect_success( mico_config_source_t source )
{
UNUSED_PARAMETER( source );
}
WEAK void mico_easylink_monitor_delegate_channel_changed( uint8_t currnet_channel )
{
UNUSED_PARAMETER( currnet_channel );
}
WEAK void mico_easylink_monitor_delegate_package_recved( uint8_t * frame, int len )
{
UNUSED_PARAMETER( frame );
UNUSED_PARAMETER( len );
}
/**
******************************************************************************
* @file system_easylink_delegate.c
* @author William Xu
* @version V1.0.0
* @date 05-May-2014
* @brief This file provide delegate functions from Easylink.
******************************************************************************
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "platform_config.h"
#include "StringUtils.h"
#include "system.h"
#define SYS_LED_TRIGGER_INTERVAL 100
#define SYS_LED_TRIGGER_INTERVAL_AFTER_EASYLINK 500
static mico_timer_t _Led_EL_timer;
static bool _Led_EL_timer_initialized = false;
static void _led_EL_Timeout_handler( void* arg )
{
(void)(arg);
MicoGpioOutputTrigger((mico_gpio_t)MICO_SYS_LED);
}
WEAK void mico_system_delegate_config_will_start( void )
{
/*Led trigger*/
if(_Led_EL_timer_initialized == true)
{
mico_stop_timer(&_Led_EL_timer);
mico_deinit_timer( &_Led_EL_timer );
_Led_EL_timer_initialized = false;
}
mico_init_timer(&_Led_EL_timer, SYS_LED_TRIGGER_INTERVAL, _led_EL_Timeout_handler, NULL);
mico_start_timer(&_Led_EL_timer);
_Led_EL_timer_initialized = true;
return;
}
WEAK void mico_system_delegate_soft_ap_will_start( void )
{
return;
}
WEAK void mico_system_delegate_config_will_stop( void )
{
if(_Led_EL_timer_initialized == true)
{
mico_stop_timer(&_Led_EL_timer);
mico_deinit_timer( &_Led_EL_timer );
_Led_EL_timer_initialized = false;
}
MicoSysLed(true);
return;
}
WEAK void mico_system_delegate_config_recv_ssid ( char *ssid, char *key )
{
UNUSED_PARAMETER(ssid);
UNUSED_PARAMETER(key);
if(_Led_EL_timer_initialized == true)
{
mico_stop_timer(&_Led_EL_timer);
mico_deinit_timer( &_Led_EL_timer );
_Led_EL_timer_initialized = false;
}
mico_init_timer(&_Led_EL_timer, SYS_LED_TRIGGER_INTERVAL_AFTER_EASYLINK, _led_EL_Timeout_handler, NULL);
mico_start_timer(&_Led_EL_timer);
_Led_EL_timer_initialized = true;
return;
}
WEAK mico_connect_fail_config_t mico_system_delegate_config_result( mico_config_source_t source, uint8_t result )
{
//system_log( "Configed by %d", source );
UNUSED_PARAMETER(source);
if(MICO_FALSE == result)
{
return RESTART_EASYLINK;
}
else
{
return EXIT_EASYLINK;
}
}
WEAK void mico_system_delegate_config_success( mico_config_source_t source )
{
//system_log( "Configed by %d", source );
UNUSED_PARAMETER(source);
return;
}
WEAK void mico_system_delegate_easylink_timeout( system_context_t *context )
{
/* so roll back to previous settings (if it has) and connect */
if ( context->flashContentInRam.micoSystemConfig.configured != unConfigured ) {
MICOReadConfiguration( context );
system_connect_wifi_normal( context );
}
else {
/*module should power down in default setting*/
micoWlanPowerOff();
}
}
WEAK OSStatus mico_system_delegate_config_recv_auth_data(char * anthData )
{
(void)(anthData);
return kNoErr;
}
WEAK void mico_easylink_monitor_delegate_will_start( void )
{
}
WEAK void mico_easylink_monitor_delegate_stoped( void )
{
}
WEAK void mico_easylink_monitor_delegate_connect_success( mico_config_source_t source )
{
UNUSED_PARAMETER( source );
}
WEAK void mico_easylink_monitor_delegate_channel_changed( uint8_t currnet_channel )
{
UNUSED_PARAMETER( currnet_channel );
}
WEAK void mico_easylink_monitor_delegate_package_recved( uint8_t * frame, int len )
{
UNUSED_PARAMETER( frame );
UNUSED_PARAMETER( len );
}

View File

@@ -1,388 +1,388 @@
/**
******************************************************************************
* @file system_easylink_monitor.c
* @author William Xu
* @version V1.0.0
* @date 20-May-2017
* @brief This file provide the easylink function for quick provisioning and
* first time configuration.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "system_internal.h"
#include "easylink_internal.h"
#include "StringUtils.h"
//#if (MICO_WLAN_CONFIG_MODE == CONFIG_MODE_EASYLINK) || (MICO_WLAN_CONFIG_MODE == CONFIG_MODE_EASYLINK_WITH_SOFTAP)
/******************************************************
* Function Declarations
******************************************************/
/* EasyLink event callback functions*/
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext );
static void easylink_complete_cb( network_InitTypeDef_st *nwkpara, system_context_t * const inContext );
static void easylink_extra_data_cb( int datalen, char* data, system_context_t * const inContext );
/* Thread perform easylink and connect to wlan */
static void easylink_monitor_thread( uint32_t inContext ); /* Perform easylink and connect to wlan */
extern void mico_wlan_monitor_no_easylink(void);
/******************************************************
* Variables Definitions
******************************************************/
static mico_timed_event_t _monitor_timed_check;
static uint8_t wlan_channel = 1;
static mico_bool_t wlan_channel_walker = MICO_TRUE;
static uint32_t wlan_channel_walker_interval = 100;
static mico_semaphore_t easylink_sem; /**< Used to suspend thread while easylink. */
static mico_semaphore_t easylink_connect_sem; /**< Used to suspend thread while connection. */
static bool easylink_success = false; /**< true: connect to wlan, false: start soft ap mode or roll back to previous settings */
static uint32_t easylink_id = 0; /**< Unique for an easylink instance. */
static mico_thread_t easylink_monitor_thread_handler = NULL;
static bool easylink_thread_force_exit = false;
static mico_config_source_t source = CONFIG_BY_NONE;
/******************************************************
* Function Definitions
******************************************************/
/* MiCO callback when WiFi status is changed */
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext )
{
switch ( event )
{
case NOTIFY_STATION_UP:
/* Connected to AP, means that the wlan configuration is right, update configuration in flash and update
bongjour txt record with new "easylink_id" */
easylink_bonjour_update( Station, easylink_id, inContext );
inContext->flashContentInRam.micoSystemConfig.configured = allConfigured;
mico_system_context_update( &inContext->flashContentInRam ); //Update Flash content
mico_rtos_set_semaphore( &easylink_connect_sem ); //Notify Easylink thread
break;
default:
break;
}
return;
}
/* MiCO callback when EasyLink is finished step 1, return SSID and KEY */
static void easylink_complete_cb( network_InitTypeDef_st *nwkpara, system_context_t * const inContext )
{
OSStatus err = kNoErr;
require_action_string( nwkpara, exit, err = kTimeoutErr, "EasyLink Timeout or terminated" );
/* Store SSID and KEY*/
mico_rtos_lock_mutex( &inContext->flashContentInRam_mutex );
memcpy( inContext->flashContentInRam.micoSystemConfig.ssid, nwkpara->wifi_ssid, maxSsidLen );
memset( inContext->flashContentInRam.micoSystemConfig.bssid, 0x0, 6 );
memcpy( inContext->flashContentInRam.micoSystemConfig.user_key, nwkpara->wifi_key, maxKeyLen );
inContext->flashContentInRam.micoSystemConfig.user_keyLength = strlen( nwkpara->wifi_key );
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = true;
mico_rtos_unlock_mutex( &inContext->flashContentInRam_mutex );
system_log("Get SSID: %s, Key: %s", inContext->flashContentInRam.micoSystemConfig.ssid, inContext->flashContentInRam.micoSystemConfig.user_key);
source = (mico_config_source_t) nwkpara->wifi_retry_interval;
exit:
if ( err != kNoErr )
{
/*EasyLink timeout or error*/
easylink_success = false;
mico_rtos_set_semaphore( &easylink_sem );
}
return;
}
/* MiCO callback when EasyLink is finished step 2, return extra data
data format: [AuthData#Identifier]<localIp/netMask/gateWay/dnsServer>
Auth data: Provide to application, application will decide if this is a proter configuration for currnet device
Identifier: Unique id for every easylink instance send by easylink mobile app
localIp/netMask/gateWay/dnsServer: Device static ip address, use DHCP if not exist
*/
static void easylink_extra_data_cb( int datalen, char* data, system_context_t * const inContext )
{
OSStatus err = kNoErr;
int index;
uint32_t *identifier, ipInfoCount;
char *debugString;
struct in_addr ipv4_addr;
debugString = DataToHexStringWithSpaces( (const uint8_t *) data, datalen );
system_log("Get user info: %s", debugString);
free( debugString );
/* Find '#' that separate authdata and identifier*/
for ( index = datalen - 1; index >= 0; index-- )
{
if ( data[index] == '#' && ((datalen - index) == 5 || (datalen - index) == 25) )
break;
}
require_action( index >= 0, exit, err = kParamErr );
/* Check auth data by device */
data[index++] = 0x0;
err = mico_system_delegate_config_recv_auth_data( data );
require_noerr( err, exit );
/* Read identifier */
identifier = (uint32_t *) &data[index];
easylink_id = *identifier;
/* Identifier: 1 x uint32_t or Identifier/localIp/netMask/gateWay/dnsServer: 5 x uint32_t */
ipInfoCount = (datalen - index) / sizeof(uint32_t);
require_action( ipInfoCount >= 1, exit, err = kParamErr );
mico_rtos_lock_mutex( &inContext->flashContentInRam_mutex );
if ( ipInfoCount == 1 )
{ //Use DHCP to obtain local ip address
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = true;
system_log("Get auth info: %s, EasyLink identifier: %lx", data, easylink_id);
} else
{ //Use static ip address
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = false;
ipv4_addr.s_addr = *(identifier+1);
strcpy( (char *) inContext->micoStatus.localIp, inet_ntoa( ipv4_addr ) );
ipv4_addr.s_addr = *(identifier+2);
strcpy( (char *) inContext->micoStatus.netMask, inet_ntoa( ipv4_addr ) );
ipv4_addr.s_addr = *(identifier+3);
strcpy( (char *) inContext->micoStatus.gateWay, inet_ntoa( ipv4_addr ) );
ipv4_addr.s_addr = *(identifier+4);
strcpy( (char *) inContext->micoStatus.dnsServer, inet_ntoa( ipv4_addr ) );
system_log("Get auth info: %s, EasyLink identifier: %lx, local IP info:%s %s %s %s ", data, easylink_id, inContext->flashContentInRam.micoSystemConfig.localIp,
inContext->flashContentInRam.micoSystemConfig.netMask, inContext->flashContentInRam.micoSystemConfig.gateWay,inContext->flashContentInRam.micoSystemConfig.dnsServer);
}
mico_rtos_unlock_mutex( &inContext->flashContentInRam_mutex );
source = CONFIG_BY_EASYLINK_V2;
exit:
if ( err != kNoErr )
{
/*EasyLink error*/
system_log("EasyLink step 2 ERROR, err: %d", err);
easylink_success = false;
} else
/* Easylink success after step 1 and step 2 */
easylink_success = true;
mico_rtos_set_semaphore( &easylink_sem );
return;
}
static OSStatus _monitor_timed_check_cb(void *arg)
{
mico_time_t current;
mico_time_get_time( &current );
if ( current > (mico_time_t) arg ) {
easylink_success = false;
mico_rtos_set_semaphore( &easylink_sem );
}
if( wlan_channel_walker == MICO_TRUE){
mico_wlan_set_channel( wlan_channel );
mico_easylink_monitor_delegate_channel_changed( wlan_channel );
wlan_channel++;
if ( wlan_channel >= 14 ) wlan_channel = 1;
}
return kNoErr;
}
static void monitor_cb( uint8_t * frame, int len )
{
mico_easylink_monitor_delegate_package_recved( frame, len );
}
static void easylink_monitor_thread( uint32_t arg )
{
OSStatus err = kNoErr;
system_context_t *context = (system_context_t *) arg;
mico_time_t current;
easylink_id = 0x0;
easylink_success = false;
easylink_thread_force_exit = false;
source = CONFIG_BY_NONE;
mico_system_notify_register( mico_notify_EASYLINK_WPS_COMPLETED, (void *) easylink_complete_cb, context );
mico_system_notify_register( mico_notify_EASYLINK_GET_EXTRA_DATA, (void *) easylink_extra_data_cb, context );
mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void *) easylink_wifi_status_cb, context );
mico_rtos_init_semaphore( &easylink_sem, 1 );
mico_rtos_init_semaphore( &easylink_connect_sem, 1 );
mico_wlan_register_monitor_cb( monitor_cb );
restart:
mico_system_delegate_config_will_start( );
system_log("Start easylink monitor mode");
mico_easylink_monitor_delegate_will_start( );
mico_wlan_start_monitor( );
wlan_channel_walker = MICO_TRUE;
mico_time_get_time( &current );
mico_rtos_register_timed_event( &_monitor_timed_check, MICO_NETWORKING_WORKER_THREAD, _monitor_timed_check_cb,
wlan_channel_walker_interval, (void *)(current + EasyLink_TimeOut) );
while( mico_rtos_get_semaphore( &easylink_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_sem, MICO_WAIT_FOREVER );
mico_rtos_deregister_timed_event( &_monitor_timed_check );
mico_wlan_stop_monitor( );
mico_easylink_monitor_delegate_stoped();
/* Easylink force exit by user, clean and exit */
if( err != kNoErr && easylink_thread_force_exit )
{
system_log("EasyLink canceled by user");
goto exit;
}
/* EasyLink Success */
if ( easylink_success == true )
{
mico_system_delegate_config_recv_ssid( context->flashContentInRam.micoSystemConfig.ssid,
context->flashContentInRam.micoSystemConfig.user_key );
system_connect_wifi_normal( context );
/* Wait for station connection */
while( mico_rtos_get_semaphore( &easylink_connect_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_connect_sem, EasyLink_ConnectWlan_Timeout );
/* Easylink force exit by user, clean and exit */
if( err != kNoErr && easylink_thread_force_exit )
{
micoWlanSuspend();
system_log("EasyLink connection canceled by user");
goto exit;
}
/*SSID or Password is not correct, module cannot connect to wlan, so restart EasyLink again*/
require_noerr_action_string( err, restart, micoWlanSuspend(), "Re-start easylink combo mode" );
/* Start bonjour service for new device discovery */
err = easylink_bonjour_start( Station, easylink_id, context );
require_noerr( err, exit );
SetTimer( 60 * 1000, easylink_remove_bonjour );
source = (source == CONFIG_BY_NONE) ? CONFIG_BY_MONITOR : source;
mico_system_delegate_config_success( source );
mico_easylink_monitor_delegate_connect_success( source );
goto exit;
}
else /* EasyLink failed */
{
/* so roll back to previous settings (if it has) and connect */
if ( context->flashContentInRam.micoSystemConfig.configured != unConfigured ) {
system_log("Roll back to previous settings");
MICOReadConfiguration( context );
system_connect_wifi_normal( context );
}
else {
/*module should power down in default setting*/
system_log("Wi-Fi power off");
micoWlanPowerOff();
}
}
exit:
easylink_thread_force_exit = false;
mico_system_delegate_config_will_stop( );
mico_system_notify_remove( mico_notify_WIFI_STATUS_CHANGED, (void *)easylink_wifi_status_cb );
mico_system_notify_remove( mico_notify_EASYLINK_WPS_COMPLETED, (void *)easylink_complete_cb );
mico_system_notify_remove( mico_notify_EASYLINK_GET_EXTRA_DATA, (void *)easylink_extra_data_cb );
mico_rtos_deinit_semaphore( &easylink_sem );
mico_rtos_deinit_semaphore( &easylink_connect_sem );
easylink_monitor_thread_handler = NULL;
mico_rtos_delete_thread( NULL );
}
OSStatus mico_easylink_monitor_channel_walker( mico_bool_t enable, uint32_t interval )
{
wlan_channel_walker = enable;
if( enable == MICO_TRUE ) wlan_channel_walker_interval = interval;
return kNoErr;
}
OSStatus mico_easylink_monitor_save_result( network_InitTypeDef_st *nwkpara )
{
system_context_t * context = system_context( );
if( context == NULL ) return kNotPreparedErr;
memcpy( context->flashContentInRam.micoSystemConfig.ssid, nwkpara->wifi_ssid, maxSsidLen );
memset( context->flashContentInRam.micoSystemConfig.bssid, 0x0, 6 );
memcpy( context->flashContentInRam.micoSystemConfig.user_key, nwkpara->wifi_key, maxKeyLen );
context->flashContentInRam.micoSystemConfig.user_keyLength = strlen( nwkpara->wifi_key );
context->flashContentInRam.micoSystemConfig.dhcpEnable = true;
system_log("Get SSID: %s, Key: %s", context->flashContentInRam.micoSystemConfig.ssid, context->flashContentInRam.micoSystemConfig.user_key);
easylink_success = true;
mico_rtos_set_semaphore( &easylink_sem );
return kNoErr;
}
OSStatus mico_easylink_monitor_with_easylink( mico_Context_t * const in_context, mico_bool_t enable )
{
OSStatus err = kUnknownErr;
require_action( in_context, exit, err = kNotPreparedErr );
easylink_remove_bonjour( );
/* easylink thread existed? stop! */
if ( easylink_monitor_thread_handler ) {
system_log("EasyLink monitor processing, force stop..");
easylink_thread_force_exit = true;
mico_rtos_thread_force_awake( &easylink_monitor_thread_handler );
mico_rtos_thread_join( &easylink_monitor_thread_handler );
}
if ( enable == MICO_TRUE ) {
err = mico_rtos_create_thread( &easylink_monitor_thread_handler, MICO_APPLICATION_PRIORITY, "EASYLINK",
easylink_monitor_thread, 0x1000, (mico_thread_arg_t) in_context );
require_noerr_string( err, exit, "ERROR: Unable to start the EasyLink monitor thread." );
/* Make sure easylink is already running, and waiting for sem trigger */
mico_rtos_delay_milliseconds( 100 );
}
exit:
return err;
}
OSStatus mico_easylink_monitor( mico_Context_t * const in_context, mico_bool_t enable )
{
mico_wlan_monitor_no_easylink();
return mico_easylink_monitor_with_easylink( in_context, enable );
}
//#endif
/**
******************************************************************************
* @file system_easylink_monitor.c
* @author William Xu
* @version V1.0.0
* @date 20-May-2017
* @brief This file provide the easylink function for quick provisioning and
* first time configuration.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "system_internal.h"
#include "easylink_internal.h"
#include "StringUtils.h"
//#if (MICO_WLAN_CONFIG_MODE == CONFIG_MODE_EASYLINK) || (MICO_WLAN_CONFIG_MODE == CONFIG_MODE_EASYLINK_WITH_SOFTAP)
/******************************************************
* Function Declarations
******************************************************/
/* EasyLink event callback functions*/
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext );
static void easylink_complete_cb( network_InitTypeDef_st *nwkpara, system_context_t * const inContext );
static void easylink_extra_data_cb( int datalen, char* data, system_context_t * const inContext );
/* Thread perform easylink and connect to wlan */
static void easylink_monitor_thread( uint32_t inContext ); /* Perform easylink and connect to wlan */
extern void mico_wlan_monitor_no_easylink(void);
/******************************************************
* Variables Definitions
******************************************************/
static mico_timed_event_t _monitor_timed_check;
static uint8_t wlan_channel = 1;
static mico_bool_t wlan_channel_walker = MICO_TRUE;
static uint32_t wlan_channel_walker_interval = 100;
static mico_semaphore_t easylink_sem; /**< Used to suspend thread while easylink. */
static mico_semaphore_t easylink_connect_sem; /**< Used to suspend thread while connection. */
static bool easylink_success = false; /**< true: connect to wlan, false: start soft ap mode or roll back to previous settings */
static uint32_t easylink_id = 0; /**< Unique for an easylink instance. */
static mico_thread_t easylink_monitor_thread_handler = NULL;
static bool easylink_thread_force_exit = false;
static mico_config_source_t source = CONFIG_BY_NONE;
static mico_connect_fail_config_t connect_fail_config = EXIT_EASYLINK;
/******************************************************
* Function Definitions
******************************************************/
/* MiCO callback when WiFi status is changed */
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext )
{
switch ( event )
{
case NOTIFY_STATION_UP:
/* Connected to AP, means that the wlan configuration is right, update configuration in flash and update
bongjour txt record with new "easylink_id" */
easylink_bonjour_update( Station, easylink_id, inContext );
inContext->flashContentInRam.micoSystemConfig.configured = allConfigured;
mico_system_context_update( &inContext->flashContentInRam ); //Update Flash content
mico_rtos_set_semaphore( &easylink_connect_sem ); //Notify Easylink thread
break;
default:
break;
}
return;
}
/* MiCO callback when EasyLink is finished step 1, return SSID and KEY */
static void easylink_complete_cb( network_InitTypeDef_st *nwkpara, system_context_t * const inContext )
{
OSStatus err = kNoErr;
require_action_string( nwkpara, exit, err = kTimeoutErr, "EasyLink Timeout or terminated" );
/* Store SSID and KEY*/
mico_rtos_lock_mutex( &inContext->flashContentInRam_mutex );
memcpy( inContext->flashContentInRam.micoSystemConfig.ssid, nwkpara->wifi_ssid, maxSsidLen );
memset( inContext->flashContentInRam.micoSystemConfig.bssid, 0x0, 6 );
memcpy( inContext->flashContentInRam.micoSystemConfig.user_key, nwkpara->wifi_key, maxKeyLen );
inContext->flashContentInRam.micoSystemConfig.user_keyLength = strlen( nwkpara->wifi_key );
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = true;
mico_rtos_unlock_mutex( &inContext->flashContentInRam_mutex );
system_log("Get SSID: %s, Key: %s", inContext->flashContentInRam.micoSystemConfig.ssid, inContext->flashContentInRam.micoSystemConfig.user_key);
source = (mico_config_source_t) nwkpara->wifi_retry_interval;
exit:
if ( err != kNoErr )
{
/*EasyLink timeout or error*/
easylink_success = false;
mico_rtos_set_semaphore( &easylink_sem );
}
return;
}
/* MiCO callback when EasyLink is finished step 2, return extra data
data format: [AuthData#Identifier]<localIp/netMask/gateWay/dnsServer>
Auth data: Provide to application, application will decide if this is a proter configuration for currnet device
Identifier: Unique id for every easylink instance send by easylink mobile app
localIp/netMask/gateWay/dnsServer: Device static ip address, use DHCP if not exist
*/
static void easylink_extra_data_cb( int datalen, char* data, system_context_t * const inContext )
{
OSStatus err = kNoErr;
int index;
uint32_t *identifier, ipInfoCount;
char *debugString;
struct in_addr ipv4_addr;
debugString = DataToHexStringWithSpaces( (const uint8_t *) data, datalen );
system_log("Get user info: %s", debugString);
free( debugString );
/* Find '#' that separate authdata and identifier*/
for ( index = datalen - 1; index >= 0; index-- )
{
if ( data[index] == '#' && ((datalen - index) == 5 || (datalen - index) == 25) )
break;
}
require_action( index >= 0, exit, err = kParamErr );
/* Check auth data by device */
data[index++] = 0x0;
err = mico_system_delegate_config_recv_auth_data( data );
require_noerr( err, exit );
/* Read identifier */
identifier = (uint32_t *) &data[index];
easylink_id = *identifier;
/* Identifier: 1 x uint32_t or Identifier/localIp/netMask/gateWay/dnsServer: 5 x uint32_t */
ipInfoCount = (datalen - index) / sizeof(uint32_t);
require_action( ipInfoCount >= 1, exit, err = kParamErr );
mico_rtos_lock_mutex( &inContext->flashContentInRam_mutex );
if ( ipInfoCount == 1 )
{ //Use DHCP to obtain local ip address
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = true;
system_log("Get auth info: %s, EasyLink identifier: %lx", data, easylink_id);
} else
{ //Use static ip address
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = false;
ipv4_addr.s_addr = *(identifier+1);
strcpy( (char *) inContext->micoStatus.localIp, inet_ntoa( ipv4_addr ) );
ipv4_addr.s_addr = *(identifier+2);
strcpy( (char *) inContext->micoStatus.netMask, inet_ntoa( ipv4_addr ) );
ipv4_addr.s_addr = *(identifier+3);
strcpy( (char *) inContext->micoStatus.gateWay, inet_ntoa( ipv4_addr ) );
ipv4_addr.s_addr = *(identifier+4);
strcpy( (char *) inContext->micoStatus.dnsServer, inet_ntoa( ipv4_addr ) );
system_log("Get auth info: %s, EasyLink identifier: %lx, local IP info:%s %s %s %s ", data, easylink_id, inContext->flashContentInRam.micoSystemConfig.localIp,
inContext->flashContentInRam.micoSystemConfig.netMask, inContext->flashContentInRam.micoSystemConfig.gateWay,inContext->flashContentInRam.micoSystemConfig.dnsServer);
}
mico_rtos_unlock_mutex( &inContext->flashContentInRam_mutex );
source = CONFIG_BY_EASYLINK_V2;
exit:
if ( err != kNoErr )
{
/*EasyLink error*/
system_log("EasyLink step 2 ERROR, err: %d", err);
easylink_success = false;
} else
/* Easylink success after step 1 and step 2 */
easylink_success = true;
mico_rtos_set_semaphore( &easylink_sem );
return;
}
static OSStatus _monitor_timed_check_cb(void *arg)
{
mico_time_t current;
mico_time_get_time( &current );
if ( current > (mico_time_t) arg ) {
easylink_success = false;
mico_rtos_set_semaphore( &easylink_sem );
}
if( wlan_channel_walker == MICO_TRUE){
mico_wlan_set_channel( wlan_channel );
mico_easylink_monitor_delegate_channel_changed( wlan_channel );
wlan_channel++;
if ( wlan_channel >= 14 ) wlan_channel = 1;
}
return kNoErr;
}
static void monitor_cb( uint8_t * frame, int len )
{
mico_easylink_monitor_delegate_package_recved( frame, len );
}
static void easylink_monitor_thread( uint32_t arg )
{
OSStatus err = kNoErr;
system_context_t *context = (system_context_t *) arg;
mico_time_t current;
easylink_id = 0x0;
easylink_success = false;
easylink_thread_force_exit = false;
source = CONFIG_BY_NONE;
mico_system_notify_register( mico_notify_EASYLINK_WPS_COMPLETED, (void *) easylink_complete_cb, context );
mico_system_notify_register( mico_notify_EASYLINK_GET_EXTRA_DATA, (void *) easylink_extra_data_cb, context );
mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void *) easylink_wifi_status_cb, context );
mico_rtos_init_semaphore( &easylink_sem, 1 );
mico_rtos_init_semaphore( &easylink_connect_sem, 1 );
mico_wlan_register_monitor_cb( monitor_cb );
restart:
mico_system_delegate_config_will_start( );
system_log("Start easylink monitor mode");
mico_easylink_monitor_delegate_will_start( );
mico_wlan_start_monitor( );
wlan_channel_walker = MICO_TRUE;
mico_time_get_time( &current );
mico_rtos_register_timed_event( &_monitor_timed_check, MICO_NETWORKING_WORKER_THREAD, _monitor_timed_check_cb,
wlan_channel_walker_interval, (void *)(current + EasyLink_TimeOut) );
while( mico_rtos_get_semaphore( &easylink_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_sem, MICO_WAIT_FOREVER );
mico_rtos_deregister_timed_event( &_monitor_timed_check );
mico_wlan_stop_monitor( );
mico_easylink_monitor_delegate_stoped();
/* Easylink force exit by user, clean and exit */
if( err != kNoErr && easylink_thread_force_exit )
{
system_log("EasyLink canceled by user");
goto exit;
}
/* EasyLink Success */
if ( easylink_success == true )
{
mico_system_delegate_config_recv_ssid( context->flashContentInRam.micoSystemConfig.ssid,
context->flashContentInRam.micoSystemConfig.user_key );
system_connect_wifi_normal( context );
/* Wait for station connection */
while( mico_rtos_get_semaphore( &easylink_connect_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_connect_sem, EasyLink_ConnectWlan_Timeout );
/* Easylink force exit by user, clean and exit */
if( err != kNoErr && easylink_thread_force_exit )
{
micoWlanSuspend();
system_log("EasyLink connection canceled by user");
goto exit;
}
source = (source == CONFIG_BY_NONE) ? CONFIG_BY_MONITOR : source;
/* Easylink connect result */
if ( err != kNoErr )
{
connect_fail_config = mico_system_delegate_config_result( source, MICO_FALSE );
if ( RESTART_EASYLINK == connect_fail_config )
{
system_log("Re-start easylink combo mode");
micoWlanSuspend( );
goto restart;
} else {
system_log("exit easylink combo mode");
micoWlanSuspendStation( );
goto exit;
}
}
else
{
mico_system_delegate_config_result( source, MICO_TRUE );
mico_easylink_monitor_delegate_connect_success( source );
}
}
else /* EasyLink failed */
{
mico_system_delegate_easylink_timeout( context );
}
exit:
easylink_thread_force_exit = false;
mico_system_delegate_config_will_stop( );
mico_system_notify_remove( mico_notify_WIFI_STATUS_CHANGED, (void *)easylink_wifi_status_cb );
mico_system_notify_remove( mico_notify_EASYLINK_WPS_COMPLETED, (void *)easylink_complete_cb );
mico_system_notify_remove( mico_notify_EASYLINK_GET_EXTRA_DATA, (void *)easylink_extra_data_cb );
mico_rtos_deinit_semaphore( &easylink_sem );
mico_rtos_deinit_semaphore( &easylink_connect_sem );
easylink_monitor_thread_handler = NULL;
mico_rtos_delete_thread( NULL );
}
OSStatus mico_easylink_monitor_channel_walker( mico_bool_t enable, uint32_t interval )
{
wlan_channel_walker = enable;
if( enable == MICO_TRUE ) wlan_channel_walker_interval = interval;
return kNoErr;
}
OSStatus mico_easylink_monitor_save_result( network_InitTypeDef_st *nwkpara )
{
system_context_t * context = system_context( );
if( context == NULL ) return kNotPreparedErr;
memcpy( context->flashContentInRam.micoSystemConfig.ssid, nwkpara->wifi_ssid, maxSsidLen );
memset( context->flashContentInRam.micoSystemConfig.bssid, 0x0, 6 );
memcpy( context->flashContentInRam.micoSystemConfig.user_key, nwkpara->wifi_key, maxKeyLen );
context->flashContentInRam.micoSystemConfig.user_keyLength = strlen( nwkpara->wifi_key );
context->flashContentInRam.micoSystemConfig.dhcpEnable = true;
system_log("Get SSID: %s, Key: %s", context->flashContentInRam.micoSystemConfig.ssid, context->flashContentInRam.micoSystemConfig.user_key);
easylink_success = true;
mico_rtos_set_semaphore( &easylink_sem );
return kNoErr;
}
OSStatus mico_easylink_monitor_with_easylink( mico_Context_t * const in_context, mico_bool_t enable )
{
OSStatus err = kNoErr;
require_action( in_context, exit, err = kNotPreparedErr );
easylink_remove_bonjour( );
/* easylink thread existed? stop! */
if ( easylink_monitor_thread_handler ) {
system_log("EasyLink monitor processing, force stop..");
easylink_thread_force_exit = true;
mico_rtos_thread_force_awake( &easylink_monitor_thread_handler );
mico_rtos_thread_join( &easylink_monitor_thread_handler );
}
if ( enable == MICO_TRUE ) {
err = mico_rtos_create_thread( &easylink_monitor_thread_handler, MICO_APPLICATION_PRIORITY, "EASYLINK",
easylink_monitor_thread, 0x1000, (mico_thread_arg_t) in_context );
require_noerr_string( err, exit, "ERROR: Unable to start the EasyLink monitor thread." );
/* Make sure easylink is already running, and waiting for sem trigger */
mico_rtos_delay_milliseconds( 100 );
}
exit:
return err;
}
OSStatus mico_easylink_monitor( mico_Context_t * const in_context, mico_bool_t enable )
{
mico_wlan_monitor_no_easylink();
return mico_easylink_monitor_with_easylink( in_context, enable );
}
//#endif

View File

@@ -1,292 +1,294 @@
/**
******************************************************************************
* @file system_easylink_softap.c
* @author William Xu
* @version V1.0.0
* @date 20-July-2015
* @brief This file provide the easylink function for quick provisioning and
* first time configuration.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "system_internal.h"
#include "StringUtils.h"
#include "HTTPUtils.h"
#include "SocketUtils.h"
#include "system.h"
#include "easylink_internal.h"
/* Internal vars and functions */
static mico_semaphore_t easylink_sem; /**< Used to suspend thread while easylink. */
static mico_semaphore_t easylink_connect_sem; /**< Used to suspend thread while connection. */
static bool easylink_success = false; /**< true: connect to wlan, false: start soft ap mode or roll back to previous settings */
static uint32_t easylinkIndentifier = 0; /**< Unique for an easylink instance. */
static mico_thread_t easylink_softap_thread_handler = NULL;
static bool easylink_thread_force_exit = false;
/* Perform easylink and connect to wlan */
static void easylink_softap_thread( uint32_t inContext );
/* MiCO callback when WiFi status is changed */
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext )
{
switch ( event )
{
case NOTIFY_STATION_UP:
/* Connected to AP, means that the wlan configuration is right, update configuration in flash and update
bongjour txt record with new "easylinkIndentifier" */
easylink_bonjour_update( Station, easylinkIndentifier, inContext );
inContext->flashContentInRam.micoSystemConfig.configured = allConfigured;
mico_system_context_update( &inContext->flashContentInRam ); //Update Flash content
mico_rtos_set_semaphore( &easylink_connect_sem ); //Notify Easylink thread
break;
case NOTIFY_AP_DOWN:
/* Remove bonjour service under soft ap interface */
mdns_suspend_record( "_easylink_config._tcp.local.", Soft_AP, true );
break;
default:
break;
}
}
OSStatus ConfigIncommingJsonMessageUAP( int fd, const uint8_t *input, size_t size, system_context_t * const inContext )
{
OSStatus err = kNoErr;
json_object *new_obj;
char *input_str = NULL;
uint8_t *httpResponse = NULL;
size_t httpResponseLen = 0;
inContext->flashContentInRam.micoSystemConfig.easyLinkByPass = EASYLINK_BYPASS_NO;
input_str = calloc( size + 1, sizeof(char) );
require_action( input_str, exit, err = kNoMemoryErr );
memcpy( input_str, input, size );
system_log("Recv config object=%s", input_str);
new_obj = json_tokener_parse( input_str );
require_action( new_obj, exit, err = kUnknownErr );
json_object_object_foreach( new_obj, key, val )
{
if ( !strcmp( key, "SSID" ) ) {
strncpy( inContext->flashContentInRam.micoSystemConfig.ssid, json_object_get_string( val ), maxSsidLen );
inContext->flashContentInRam.micoSystemConfig.channel = 0;
memset( inContext->flashContentInRam.micoSystemConfig.bssid, 0x0, 6 );
inContext->flashContentInRam.micoSystemConfig.security = SECURITY_TYPE_AUTO;
memcpy( inContext->flashContentInRam.micoSystemConfig.key, inContext->flashContentInRam.micoSystemConfig.user_key, maxKeyLen );
inContext->flashContentInRam.micoSystemConfig.keyLength = inContext->flashContentInRam.micoSystemConfig.user_keyLength;
}
else if ( !strcmp( key, "PASSWORD" ) ) {
inContext->flashContentInRam.micoSystemConfig.security = SECURITY_TYPE_AUTO;
strncpy( inContext->flashContentInRam.micoSystemConfig.key, json_object_get_string( val ), maxKeyLen );
strncpy( inContext->flashContentInRam.micoSystemConfig.user_key, json_object_get_string( val ), maxKeyLen );
inContext->flashContentInRam.micoSystemConfig.keyLength = strlen( inContext->flashContentInRam.micoSystemConfig.key );
inContext->flashContentInRam.micoSystemConfig.user_keyLength = strlen( inContext->flashContentInRam.micoSystemConfig.key );
memcpy( inContext->flashContentInRam.micoSystemConfig.key, inContext->flashContentInRam.micoSystemConfig.user_key, maxKeyLen );
inContext->flashContentInRam.micoSystemConfig.keyLength = inContext->flashContentInRam.micoSystemConfig.user_keyLength;
}
else if ( !strcmp( key, "DHCP" ) ) {
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = json_object_get_boolean( val );
}
else if ( !strcmp( key, "IDENTIFIER" ) ) {
easylinkIndentifier = (uint32_t) json_object_get_int( val );
}
else if ( !strcmp( key, "IP" ) ) {
strncpy( inContext->flashContentInRam.micoSystemConfig.localIp, json_object_get_string( val ), maxIpLen );
}
else if ( !strcmp( key, "NETMASK" ) ) {
strncpy( inContext->flashContentInRam.micoSystemConfig.netMask, json_object_get_string( val ), maxIpLen );
}
else if ( !strcmp( key, "GATEWAY" ) ) {
strncpy( inContext->flashContentInRam.micoSystemConfig.gateWay, json_object_get_string( val ), maxIpLen );
}
else if ( !strcmp( key, "DNS1" ) ) {
strncpy( inContext->flashContentInRam.micoSystemConfig.dnsServer, json_object_get_string( val ), maxIpLen );
}
}
json_object_put( new_obj );
err = CreateSimpleHTTPOKMessage( &httpResponse, &httpResponseLen );
require_noerr( err, exit );
err = SocketSend( fd, httpResponse, httpResponseLen );
require_noerr( err, exit );
mico_rtos_delay_milliseconds( 1000 );
easylink_success = true;
if( easylink_sem ) mico_rtos_set_semaphore( &easylink_sem );
exit:
if ( input_str ) free( input_str );
if(httpResponse) free(httpResponse);
return err;
}
void easylink_softap_thread( uint32_t inContext )
{
system_log_trace();
OSStatus err = kNoErr;
system_context_t *context = (system_context_t *) inContext;
network_InitTypeDef_st wNetConfig;
easylinkIndentifier = 0x0;
easylink_success = false;
easylink_thread_force_exit = false;
mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void *) easylink_wifi_status_cb, (void *) inContext );
mico_rtos_init_semaphore( &easylink_sem, 1 );
mico_rtos_init_semaphore( &easylink_connect_sem, 1 );
restart:
micoWlanSuspend( );
mico_thread_msleep( 20 );
mico_system_delegate_config_will_start( );
memset( &wNetConfig, 0, sizeof(network_InitTypeDef_st) );
wNetConfig.wifi_mode = Soft_AP;
snprintf( wNetConfig.wifi_ssid, 32, "EasyLink_%c%c%c%c%c%c",
context->micoStatus.mac[9], context->micoStatus.mac[10], context->micoStatus.mac[12],
context->micoStatus.mac[13], context->micoStatus.mac[15], context->micoStatus.mac[16] );
strcpy( (char*) wNetConfig.wifi_key, "" );
strcpy( (char*) wNetConfig.local_ip_addr, "10.10.10.1" );
strcpy( (char*) wNetConfig.net_mask, "255.255.255.0" );
strcpy( (char*) wNetConfig.gateway_ip_addr, "10.10.10.1" );
wNetConfig.dhcpMode = DHCP_Server;
micoWlanStart( &wNetConfig );
system_log("Establish soft ap: %s.....", wNetConfig.wifi_ssid);
/* Start bonjour service for device discovery under soft ap mode */
err = easylink_bonjour_start( Soft_AP, 0, context );
require_noerr( err, exit );
while( mico_rtos_get_semaphore( &easylink_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_sem, MICO_WAIT_FOREVER );
micoWlanSuspendSoftAP();
/* Easylink force exit by user, clean and exit */
if( err != kNoErr && easylink_thread_force_exit )
{
system_log("EasyLink canceled by user");
goto exit;
}
/* EasyLink Success */
if ( easylink_success == true ) {
mico_system_delegate_config_recv_ssid( context->flashContentInRam.micoSystemConfig.ssid,
context->flashContentInRam.micoSystemConfig.user_key );
mico_thread_sleep(1);
system_connect_wifi_normal( context );
/* Wait for station connection */
while ( mico_rtos_get_semaphore( &easylink_connect_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_connect_sem, EasyLink_ConnectWlan_Timeout );
/* Easylink force exit by user, clean and exit */
if ( err != kNoErr && easylink_thread_force_exit )
{
micoWlanSuspend( );
system_log("EasyLink connection canceled by user");
goto exit;
}
/*SSID or Password is not correct, module cannot connect to wlan, so restart EasyLink again*/
require_noerr_action_string( err, restart, micoWlanSuspend(), "Re-start easylink softap mode" );
mico_system_delegate_config_success( CONFIG_BY_SOFT_AP );
/* Start bonjour service for new device discovery */
err = easylink_bonjour_start( Station, easylinkIndentifier, context );
require_noerr( err, exit );
SetTimer( 60 * 1000, easylink_remove_bonjour );
goto exit;
}
else /* EasyLink failed */
{
/*so roll back to previous settings (if it has) and connect*/
if(context->flashContentInRam.micoSystemConfig.configured != unConfigured)
{
system_log("Roll back to previous settings");
MICOReadConfiguration( context );
#ifdef EasyLink_Needs_Reboot
context->flashContentInRam.micoSystemConfig.configured = allConfigured;
mico_system_context_update( &context->flashContentInRam );
#endif
system_connect_wifi_normal( context );
}
else {
/*module should power down in default setting*/
system_log("Wi-Fi power off");
micoWlanPowerOff( );
}
}
exit:
easylink_thread_force_exit = false;
mico_system_delegate_config_will_stop( );
mico_system_notify_remove( mico_notify_WIFI_STATUS_CHANGED, (void *) easylink_wifi_status_cb );
#ifndef MICO_CONFIG_SERVER_ENABLE
config_server_stop( );
#endif
mico_rtos_deinit_semaphore( &easylink_sem );
mico_rtos_deinit_semaphore( &easylink_connect_sem );
easylink_softap_thread_handler = NULL;
mico_rtos_delete_thread( NULL );
}
OSStatus mico_easylink_softap( mico_Context_t * const in_context, mico_bool_t enable )
{
OSStatus err = kUnknownErr;
require_action( in_context, exit, err = kNotPreparedErr );
easylink_remove_bonjour( );
/* easylink soft thread existed? stop! */
if ( easylink_softap_thread_handler ) {
system_log("EasyLink SoftAP processing, force stop..");
easylink_thread_force_exit = true;
mico_rtos_thread_force_awake( &easylink_softap_thread_handler );
mico_rtos_thread_join( &easylink_softap_thread_handler );
}
if ( enable == MICO_TRUE ) {
/* Start config server */
err = config_server_start( );
require_noerr( err, exit );
err = mico_rtos_create_thread( &easylink_softap_thread_handler, MICO_APPLICATION_PRIORITY, "EASYLINK AP",
easylink_softap_thread, 0x1000, (mico_thread_arg_t) in_context );
require_noerr_string( err, exit, "ERROR: Unable to start the EasyLink thread." );
/* Make sure easylink softap is already running, and waiting for sem trigger */
mico_rtos_delay_milliseconds( 1000 );
}
exit:
return err;
}
//#endif
/**
******************************************************************************
* @file system_easylink_softap.c
* @author William Xu
* @version V1.0.0
* @date 20-July-2015
* @brief This file provide the easylink function for quick provisioning and
* first time configuration.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "system_internal.h"
#include "StringUtils.h"
#include "HTTPUtils.h"
#include "SocketUtils.h"
#include "system.h"
#include "easylink_internal.h"
/* Internal vars and functions */
static mico_semaphore_t easylink_sem; /**< Used to suspend thread while easylink. */
static mico_semaphore_t easylink_connect_sem; /**< Used to suspend thread while connection. */
static bool easylink_success = false; /**< true: connect to wlan, false: start soft ap mode or roll back to previous settings */
static uint32_t easylinkIndentifier = 0; /**< Unique for an easylink instance. */
static mico_thread_t easylink_softap_thread_handler = NULL;
static bool easylink_thread_force_exit = false;
/* Perform easylink and connect to wlan */
static void easylink_softap_thread( uint32_t inContext );
/* MiCO callback when WiFi status is changed */
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext )
{
switch ( event )
{
case NOTIFY_STATION_UP:
/* Connected to AP, means that the wlan configuration is right, update configuration in flash and update
bongjour txt record with new "easylinkIndentifier" */
easylink_bonjour_update( Station, easylinkIndentifier, inContext );
inContext->flashContentInRam.micoSystemConfig.configured = allConfigured;
mico_system_context_update( &inContext->flashContentInRam ); //Update Flash content
mico_rtos_set_semaphore( &easylink_connect_sem ); //Notify Easylink thread
break;
case NOTIFY_AP_DOWN:
/* Remove bonjour service under soft ap interface */
mdns_suspend_record( "_easylink_config._tcp.local.", Soft_AP, true );
break;
default:
break;
}
}
OSStatus ConfigIncommingJsonMessageUAP( int fd, const uint8_t *input, size_t size, system_context_t * const inContext )
{
OSStatus err = kNoErr;
json_object *new_obj;
char *input_str = NULL;
uint8_t *httpResponse = NULL;
size_t httpResponseLen = 0;
inContext->flashContentInRam.micoSystemConfig.easyLinkByPass = EASYLINK_BYPASS_NO;
input_str = calloc( size + 1, sizeof(char) );
require_action( input_str, exit, err = kNoMemoryErr );
memcpy( input_str, input, size );
system_log("Recv config object=%s", input_str);
new_obj = json_tokener_parse( input_str );
require_action( new_obj, exit, err = kUnknownErr );
json_object_object_foreach( new_obj, key, val )
{
if ( !strcmp( key, "SSID" ) ) {
strncpy( inContext->flashContentInRam.micoSystemConfig.ssid, json_object_get_string( val ), maxSsidLen );
inContext->flashContentInRam.micoSystemConfig.channel = 0;
memset( inContext->flashContentInRam.micoSystemConfig.bssid, 0x0, 6 );
inContext->flashContentInRam.micoSystemConfig.security = SECURITY_TYPE_AUTO;
memcpy( inContext->flashContentInRam.micoSystemConfig.key, inContext->flashContentInRam.micoSystemConfig.user_key, maxKeyLen );
inContext->flashContentInRam.micoSystemConfig.keyLength = inContext->flashContentInRam.micoSystemConfig.user_keyLength;
}
else if ( !strcmp( key, "PASSWORD" ) ) {
inContext->flashContentInRam.micoSystemConfig.security = SECURITY_TYPE_AUTO;
strncpy( inContext->flashContentInRam.micoSystemConfig.key, json_object_get_string( val ), maxKeyLen );
strncpy( inContext->flashContentInRam.micoSystemConfig.user_key, json_object_get_string( val ), maxKeyLen );
inContext->flashContentInRam.micoSystemConfig.keyLength = strlen( inContext->flashContentInRam.micoSystemConfig.key );
inContext->flashContentInRam.micoSystemConfig.user_keyLength = strlen( inContext->flashContentInRam.micoSystemConfig.key );
memcpy( inContext->flashContentInRam.micoSystemConfig.key, inContext->flashContentInRam.micoSystemConfig.user_key, maxKeyLen );
inContext->flashContentInRam.micoSystemConfig.keyLength = inContext->flashContentInRam.micoSystemConfig.user_keyLength;
}
else if ( !strcmp( key, "DHCP" ) ) {
inContext->flashContentInRam.micoSystemConfig.dhcpEnable = json_object_get_boolean( val );
}
else if ( !strcmp( key, "IDENTIFIER" ) ) {
easylinkIndentifier = (uint32_t) json_object_get_int( val );
}
else if ( !strcmp( key, "IP" ) ) {
strncpy( inContext->flashContentInRam.micoSystemConfig.localIp, json_object_get_string( val ), maxIpLen );
}
else if ( !strcmp( key, "NETMASK" ) ) {
strncpy( inContext->flashContentInRam.micoSystemConfig.netMask, json_object_get_string( val ), maxIpLen );
}
else if ( !strcmp( key, "GATEWAY" ) ) {
strncpy( inContext->flashContentInRam.micoSystemConfig.gateWay, json_object_get_string( val ), maxIpLen );
}
else if ( !strcmp( key, "DNS1" ) ) {
strncpy( inContext->flashContentInRam.micoSystemConfig.dnsServer, json_object_get_string( val ), maxIpLen );
}
}
json_object_put( new_obj );
err = CreateSimpleHTTPOKMessage( &httpResponse, &httpResponseLen );
require_noerr( err, exit );
err = SocketSend( fd, httpResponse, httpResponseLen );
require_noerr( err, exit );
mico_rtos_delay_milliseconds( 1000 );
easylink_success = true;
if( easylink_sem ) mico_rtos_set_semaphore( &easylink_sem );
#ifdef MICO_EASYLINK_AND_SOFTAP_ENABLED
easylink_uap_success(easylinkIndentifier);
#endif
exit:
if ( input_str ) free( input_str );
if(httpResponse) free(httpResponse);
return err;
}
void easylink_softap_thread( uint32_t inContext )
{
system_log_trace();
OSStatus err = kNoErr;
system_context_t *context = (system_context_t *) inContext;
network_InitTypeDef_st wNetConfig;
easylinkIndentifier = 0x0;
easylink_success = false;
easylink_thread_force_exit = false;
mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void *) easylink_wifi_status_cb, (void *) inContext );
mico_rtos_init_semaphore( &easylink_sem, 1 );
mico_rtos_init_semaphore( &easylink_connect_sem, 1 );
restart:
micoWlanSuspend( );
mico_thread_msleep( 20 );
mico_system_delegate_config_will_start( );
memset( &wNetConfig, 0, sizeof(network_InitTypeDef_st) );
wNetConfig.wifi_mode = Soft_AP;
snprintf( wNetConfig.wifi_ssid, 32, "EasyLink_%c%c%c%c%c%c",
context->micoStatus.mac[9], context->micoStatus.mac[10], context->micoStatus.mac[12],
context->micoStatus.mac[13], context->micoStatus.mac[15], context->micoStatus.mac[16] );
strcpy( (char*) wNetConfig.wifi_key, "" );
strcpy( (char*) wNetConfig.local_ip_addr, "10.10.10.1" );
strcpy( (char*) wNetConfig.net_mask, "255.255.255.0" );
strcpy( (char*) wNetConfig.gateway_ip_addr, "10.10.10.1" );
wNetConfig.dhcpMode = DHCP_Server;
micoWlanStart( &wNetConfig );
system_log("Establish soft ap: %s.....", wNetConfig.wifi_ssid);
/* Start bonjour service for device discovery under soft ap mode */
err = easylink_bonjour_start( Soft_AP, 0, context );
require_noerr( err, exit );
while( mico_rtos_get_semaphore( &easylink_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_sem, MICO_WAIT_FOREVER );
micoWlanSuspendSoftAP();
/* Easylink force exit by user, clean and exit */
if( err != kNoErr && easylink_thread_force_exit )
{
system_log("EasyLink canceled by user");
goto exit;
}
/* EasyLink Success */
if ( easylink_success == true ) {
mico_system_delegate_config_recv_ssid( context->flashContentInRam.micoSystemConfig.ssid,
context->flashContentInRam.micoSystemConfig.user_key );
mico_thread_sleep(1);
system_connect_wifi_normal( context );
/* Wait for station connection */
while ( mico_rtos_get_semaphore( &easylink_connect_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_connect_sem, EasyLink_ConnectWlan_Timeout );
/* Easylink force exit by user, clean and exit */
if ( err != kNoErr && easylink_thread_force_exit )
{
micoWlanSuspend( );
system_log("EasyLink connection canceled by user");
goto exit;
}
/*SSID or Password is not correct, module cannot connect to wlan, so restart EasyLink again*/
require_noerr_action_string( err, restart, micoWlanSuspend(), "Re-start easylink softap mode" );
mico_system_delegate_config_success( CONFIG_BY_SOFT_AP );
/* Start bonjour service for new device discovery */
err = easylink_bonjour_start( Station, easylinkIndentifier, context );
require_noerr( err, exit );
SetTimer( 60 * 1000, easylink_remove_bonjour );
goto exit;
}
else /* EasyLink failed */
{
/*so roll back to previous settings (if it has) and connect*/
if(context->flashContentInRam.micoSystemConfig.configured != unConfigured)
{
system_log("Roll back to previous settings");
MICOReadConfiguration( context );
#ifdef EasyLink_Needs_Reboot
context->flashContentInRam.micoSystemConfig.configured = allConfigured;
mico_system_context_update( &context->flashContentInRam );
#endif
system_connect_wifi_normal( context );
}
else {
/*module should power down in default setting*/
system_log("Wi-Fi power off");
micoWlanPowerOff( );
}
}
exit:
easylink_thread_force_exit = false;
mico_system_delegate_config_will_stop( );
mico_system_notify_remove( mico_notify_WIFI_STATUS_CHANGED, (void *) easylink_wifi_status_cb );
#ifndef MICO_CONFIG_SERVER_ENABLE
config_server_stop( );
#endif
mico_rtos_deinit_semaphore( &easylink_sem );
mico_rtos_deinit_semaphore( &easylink_connect_sem );
easylink_softap_thread_handler = NULL;
mico_rtos_delete_thread( NULL );
}
OSStatus mico_easylink_softap( mico_Context_t * const in_context, mico_bool_t enable )
{
OSStatus err = kUnknownErr;
require_action( in_context, exit, err = kNotPreparedErr );
easylink_remove_bonjour( );
/* easylink soft thread existed? stop! */
if ( easylink_softap_thread_handler ) {
system_log("EasyLink SoftAP processing, force stop..");
easylink_thread_force_exit = true;
mico_rtos_thread_force_awake( &easylink_softap_thread_handler );
mico_rtos_thread_join( &easylink_softap_thread_handler );
}
if ( enable == MICO_TRUE ) {
/* Start config server */
err = config_server_start( );
require_noerr( err, exit );
err = mico_rtos_create_thread( &easylink_softap_thread_handler, MICO_APPLICATION_PRIORITY, "EASYLINK AP",
easylink_softap_thread, 0x1000, (mico_thread_arg_t) in_context );
require_noerr_string( err, exit, "ERROR: Unable to start the EasyLink thread." );
/* Make sure easylink softap is already running, and waiting for sem trigger */
mico_rtos_delay_milliseconds( 1000 );
}
exit:
return err;
}
//#endif

View File

@@ -1,134 +1,134 @@
/**
******************************************************************************
* @file system_easylink.c
* @author William Xu
* @version V1.0.0
* @date 20-July-2015
* @brief This file provide the easylink function for quick provisioning and
* first time configuration.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "system_internal.h"
#include "StringUtils.h"
#include "system.h"
#include "easylink_internal.h"
//#if (MICO_WLAN_CONFIG_MODE == CONFIG_MODE_USER)
/******************************************************
* Function Declarations
******************************************************/
/* Perform easylink and connect to wlan */
static void easylink_usr_thread( uint32_t inContext );
/******************************************************
* Variables Definitions
******************************************************/
static mico_semaphore_t easylink_connect_sem; /**< Used to suspend thread while connection. */
static mico_thread_t easylink_usr_thread_handler = NULL;
static bool easylink_thread_force_exit = false;
/* MiCO callback when WiFi status is changed */
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext )
{
system_log_trace();
require( inContext, exit );
switch ( event )
{
case NOTIFY_STATION_UP:
/* Connected to AP, means that the wlan configuration is right, update configuration in flash */
inContext->flashContentInRam.micoSystemConfig.configured = allConfigured;
mico_system_context_update( &inContext->flashContentInRam ); //Update Flash content
mico_rtos_set_semaphore( &easylink_connect_sem ); //Notify Easylink thread
break;
default:
break;
}
exit:
return;
}
static void easylink_usr_thread( uint32_t inContext )
{
system_log_trace();
OSStatus err = kNoErr;
system_context_t *Context = (system_context_t *) inContext;
easylink_thread_force_exit = false;
mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void *)easylink_wifi_status_cb, (void *) Context );
mico_rtos_init_semaphore( &easylink_connect_sem, 1 );
system_log("Start easylink user mode");
mico_system_delegate_config_will_start( );
/* Developer should save the ssid/key to system_context_t and connect to AP.
* NOTIFY_STATION_UP event will save the new ssid, key to flash and wake up the easylink routine */
while ( mico_rtos_get_semaphore( &easylink_connect_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_connect_sem, MICO_WAIT_FOREVER );
/* Easylink force exit by user, clean and exit */
if ( err != kNoErr && easylink_thread_force_exit ){
micoWlanSuspend( );
system_log("EasyLink connection canceled by user");
easylink_thread_force_exit = false;
goto exit;
}
mico_system_delegate_config_success( CONFIG_BY_USER );
exit:
mico_system_delegate_config_will_stop( );
mico_system_notify_remove( mico_notify_WIFI_STATUS_CHANGED, (void *) easylink_wifi_status_cb );
mico_rtos_deinit_semaphore( &easylink_connect_sem );
easylink_usr_thread_handler = NULL;
mico_rtos_delete_thread( NULL );
}
OSStatus mico_easylink_usr( mico_Context_t * const in_context, mico_bool_t enable )
{
OSStatus err = kUnknownErr;
require_action( in_context, exit, err = kNotPreparedErr );
easylink_remove_bonjour( );
/* easylink thread existed? stop! */
if ( easylink_usr_thread_handler ) {
/* easylink usr thread existed? stop! */
system_log("EasyLink usr processing, force stop..");
easylink_thread_force_exit = true;
mico_rtos_thread_force_awake( &easylink_usr_thread_handler );
mico_rtos_thread_join( &easylink_usr_thread_handler );
}
if ( enable == MICO_TRUE ) {
err = mico_rtos_create_thread( &easylink_usr_thread_handler, MICO_APPLICATION_PRIORITY, "EASYLINK USR",
easylink_usr_thread, 0x1000, (mico_thread_arg_t) in_context );
require_noerr_string( err, exit, "ERROR: Unable to start the EasyLink usr thread." );
/* Make sure easylink is already running, and waiting for sem trigger */
mico_rtos_delay_milliseconds( 100 );
}
exit:
return err;
}
//#endif
/**
******************************************************************************
* @file system_easylink.c
* @author William Xu
* @version V1.0.0
* @date 20-July-2015
* @brief This file provide the easylink function for quick provisioning and
* first time configuration.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "system_internal.h"
#include "StringUtils.h"
#include "system.h"
#include "easylink_internal.h"
//#if (MICO_WLAN_CONFIG_MODE == CONFIG_MODE_USER)
/******************************************************
* Function Declarations
******************************************************/
/* Perform easylink and connect to wlan */
static void easylink_usr_thread( uint32_t inContext );
/******************************************************
* Variables Definitions
******************************************************/
static mico_semaphore_t easylink_connect_sem; /**< Used to suspend thread while connection. */
static mico_thread_t easylink_usr_thread_handler = NULL;
static bool easylink_thread_force_exit = false;
/* MiCO callback when WiFi status is changed */
static void easylink_wifi_status_cb( WiFiEvent event, system_context_t * const inContext )
{
system_log_trace();
require( inContext, exit );
switch ( event )
{
case NOTIFY_STATION_UP:
/* Connected to AP, means that the wlan configuration is right, update configuration in flash */
inContext->flashContentInRam.micoSystemConfig.configured = allConfigured;
mico_system_context_update( &inContext->flashContentInRam ); //Update Flash content
mico_rtos_set_semaphore( &easylink_connect_sem ); //Notify Easylink thread
break;
default:
break;
}
exit:
return;
}
static void easylink_usr_thread( uint32_t inContext )
{
system_log_trace();
OSStatus err = kNoErr;
system_context_t *Context = (system_context_t *) inContext;
easylink_thread_force_exit = false;
mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void *)easylink_wifi_status_cb, (void *) Context );
mico_rtos_init_semaphore( &easylink_connect_sem, 1 );
system_log("Start easylink user mode");
mico_system_delegate_config_will_start( );
/* Developer should save the ssid/key to system_context_t and connect to AP.
* NOTIFY_STATION_UP event will save the new ssid, key to flash and wake up the easylink routine */
while ( mico_rtos_get_semaphore( &easylink_connect_sem, 0 ) == kNoErr );
err = mico_rtos_get_semaphore( &easylink_connect_sem, MICO_WAIT_FOREVER );
/* Easylink force exit by user, clean and exit */
if ( err != kNoErr && easylink_thread_force_exit ){
micoWlanSuspend( );
system_log("EasyLink connection canceled by user");
easylink_thread_force_exit = false;
goto exit;
}
mico_system_delegate_config_success( CONFIG_BY_USER );
exit:
mico_system_delegate_config_will_stop( );
mico_system_notify_remove( mico_notify_WIFI_STATUS_CHANGED, (void *) easylink_wifi_status_cb );
mico_rtos_deinit_semaphore( &easylink_connect_sem );
easylink_usr_thread_handler = NULL;
mico_rtos_delete_thread( NULL );
}
OSStatus mico_easylink_usr( mico_Context_t * const in_context, mico_bool_t enable )
{
OSStatus err = kUnknownErr;
require_action( in_context, exit, err = kNotPreparedErr );
easylink_remove_bonjour( );
/* easylink thread existed? stop! */
if ( easylink_usr_thread_handler ) {
/* easylink usr thread existed? stop! */
system_log("EasyLink usr processing, force stop..");
easylink_thread_force_exit = true;
mico_rtos_thread_force_awake( &easylink_usr_thread_handler );
mico_rtos_thread_join( &easylink_usr_thread_handler );
}
if ( enable == MICO_TRUE ) {
err = mico_rtos_create_thread( &easylink_usr_thread_handler, MICO_APPLICATION_PRIORITY, "EASYLINK USR",
easylink_usr_thread, 0x1000, (mico_thread_arg_t) in_context );
require_noerr_string( err, exit, "ERROR: Unable to start the EasyLink usr thread." );
/* Make sure easylink is already running, and waiting for sem trigger */
mico_rtos_delay_milliseconds( 100 );
}
exit:
return err;
}
//#endif

View File

@@ -1,75 +1,75 @@
/**
******************************************************************************
* @file mico_easylink_wac.c
* @author William Xu
* @version V1.0.0
* @date 05-May-2014
* @brief This file provide header file for start a Apple WAC (wireless accessory
* configuration) function thread.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "system_internal.h"
#include "MFi_WAC.h"
#include "StringUtils.h"
#define BUNDLE_SEED_ID "C6P64J2MZX"
#define EA_PROTOCOL "com.issc.datapath"
const char *eaProtocols[1] = {EA_PROTOCOL};
OSStatus mico_easylink_wac( mico_Context_t * const inContext, mico_bool_t enable )
{
OSStatus err = kNoErr;
IPStatusTypedef para;
uint8_t major_ver, minor_ver, revision;
if( enable == FALSE ) {
return mfi_wac_stop();
}
mfi_wac_lib_version( &major_ver, &minor_ver, &revision );
system_log( "Import MFi WAC library v%d.%d.%d", major_ver, minor_ver, revision );
WACPlatformParameters_t* WAC_Params = NULL;
WAC_Params = calloc(1, sizeof(WACPlatformParameters_t));
require(WAC_Params, exit);
micoWlanGetIPStatus(&para, Station);
str2hex((unsigned char *)para.mac, WAC_Params->macAddress, 6);
WAC_Params->isUnconfigured = 1;
WAC_Params->supportsAirPlay = 0;
WAC_Params->supportsAirPrint = 0;
WAC_Params->supports2_4GHzWiFi = 1;
WAC_Params->supports5GHzWiFi = 0;
WAC_Params->supportsWakeOnWireless = 0;
WAC_Params->firmwareRevision = FIRMWARE_REVISION;
WAC_Params->hardwareRevision = HARDWARE_REVISION;
WAC_Params->serialNumber = SERIAL_NUMBER;
WAC_Params->name = inContext->micoSystemConfig.name;
WAC_Params->model = MODEL;
WAC_Params->manufacturer = MANUFACTURER;
WAC_Params->numEAProtocols = 1;
WAC_Params->eaBundleSeedID = BUNDLE_SEED_ID;
WAC_Params->eaProtocols = (char **)eaProtocols;
err = mfi_wac_start( inContext, WAC_Params, MICO_I2C_CP, 1200 );
require_noerr(err, exit);
exit:
free(WAC_Params);
return err;
}
/**
******************************************************************************
* @file mico_easylink_wac.c
* @author William Xu
* @version V1.0.0
* @date 05-May-2014
* @brief This file provide header file for start a Apple WAC (wireless accessory
* configuration) function thread.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include "mico.h"
#include "system_internal.h"
#include "MFi_WAC.h"
#include "StringUtils.h"
#define BUNDLE_SEED_ID "C6P64J2MZX"
#define EA_PROTOCOL "com.issc.datapath"
const char *eaProtocols[1] = {EA_PROTOCOL};
OSStatus mico_easylink_wac( mico_Context_t * const inContext, mico_bool_t enable )
{
OSStatus err = kNoErr;
IPStatusTypedef para;
uint8_t major_ver, minor_ver, revision;
if( enable == FALSE ) {
return mfi_wac_stop();
}
mfi_wac_lib_version( &major_ver, &minor_ver, &revision );
system_log( "Import MFi WAC library v%d.%d.%d", major_ver, minor_ver, revision );
WACPlatformParameters_t* WAC_Params = NULL;
WAC_Params = calloc(1, sizeof(WACPlatformParameters_t));
require(WAC_Params, exit);
micoWlanGetIPStatus(&para, Station);
str2hex((unsigned char *)para.mac, WAC_Params->macAddress, 6);
WAC_Params->isUnconfigured = 1;
WAC_Params->supportsAirPlay = 0;
WAC_Params->supportsAirPrint = 0;
WAC_Params->supports2_4GHzWiFi = 1;
WAC_Params->supports5GHzWiFi = 0;
WAC_Params->supportsWakeOnWireless = 0;
WAC_Params->firmwareRevision = FIRMWARE_REVISION;
WAC_Params->hardwareRevision = HARDWARE_REVISION;
WAC_Params->serialNumber = SERIAL_NUMBER;
WAC_Params->name = inContext->micoSystemConfig.name;
WAC_Params->model = MODEL;
WAC_Params->manufacturer = MANUFACTURER;
WAC_Params->numEAProtocols = 1;
WAC_Params->eaBundleSeedID = BUNDLE_SEED_ID;
WAC_Params->eaProtocols = (char **)eaProtocols;
err = mfi_wac_start( inContext, WAC_Params, MICO_I2C_CP, 1200 );
require_noerr(err, exit);
exit:
free(WAC_Params);
return err;
}