⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wps_userapi.c

📁 WiFi Protected Setup (WPS) 又叫Simple config。 是无线局域网领域推出的新协议
💻 C
字号:
/*
 *  WPS_USERAPI.C : WPS User Application Interface Implementation
 * 
 *  ver       date        author      comment
 *  0.0.1     08/02/21    Gao Hua     First
 */

#include "wps_userapi.h"
#include "wps_wlandrv.h"
#include "wps_enrollee.h"
#include "wps_queue.h"
#include "wps_data_element.h"
#include "wps_callback.h"


typedef struct _tag_tried_pin_ap {
	wps_queue link;
	WPS_AP_DESC ap;
}TRIED_PIN_AP;

static WPS_THREAD_DESC wps_enrol_thread = NULL;
static WPS_SEM_DESC wps_enrol_sem = NULL;
static struct enrollee *wps_enrol_ptr = NULL;
static WPS_u8 wps_running = 0;
static wps_queue *tyied_pin_ap_queue = NULL;
static WPS_u8 wps_enrol_stop_flag;
static WPS_u32 wps_start_time;
static WPS_u32 wps_timeout_value;
static WPS_u8 wps_enrol_mode;
static WPS_char wps_enrol_pin[9];
WPS_USER_CALLBACK wps_enrol_callback;


/*---------------------------------------------------------------------------*/
struct enrollee *get_enrollee_ptr(void)
{
	return wps_enrol_ptr;
}

WPS_u8 get_enrollee_mode(void)
{
	return wps_enrol_mode;
}

const WPS_char *get_enrollee_pin(void)
{
	return wps_enrol_pin;
}
/*---------------------------------------------------------------------------*/


static int is_pin_ap_tried(WPS_AP_DESC *ap)
{
	int ret = 0;
	wps_queue *temp = tyied_pin_ap_queue;
	WPS_AP_DESC *temp_ap;
	
	while (temp) {
		temp_ap = &((TRIED_PIN_AP *)(temp->q_body))->ap;
		if (WPS_MEM_CMP(ap->bssid, temp_ap->bssid, 6) == 0) {
			ret = 1;
			break;
		}
		temp = temp->q_forw;
	}
	
	return ret;
}

static void add_tried_pin_ap_queue(WPS_AP_DESC *ap)
{
	TRIED_PIN_AP *p;
	
	p = (TRIED_PIN_AP *)WPS_MALLOC(sizeof(TRIED_PIN_AP));
	wps_init_que(&p->link, (void *)p);
	p->ap = *ap;
	wps_append_que(&tyied_pin_ap_queue, &p->link);
}

static void empty_tried_pin_ap_queue(void)
{
	wps_queue *temp;
	
	while (tyied_pin_ap_queue) {
		temp = tyied_pin_ap_queue;
		wps_remove_que(&tyied_pin_ap_queue, temp);
		WPS_MFREE(get_qbody(temp));
	}
}

/*
 * Return value:
 *  0: OK
 * -1: No such ap
 * -2: PBC session overlap
*/
static int wps_enrol_select_ap(WPS_u8 mode, WPS_AP_DESC *selected_ap)
{
	int i;
	WPS_AP_DESC ap_array[32];
	WPS_AP_DESC *ap;
	int ap_num, dataLen;
	WPS_u8 *p;
	int bConfigured, b1, b2, bDPIDExistButUnmatch;
	WPS_u16    DevicePasswordID = DPID_DEFAULT;
	int        n = 0;
	int        retIndex = -1;
	
	ap_num = Wlan_GetWpsApList(ap_array, 32);
	if (ap_num == -1) {
#if ENROLLEE_DEBUG
		WPS_PRINTF("%s: Found no AP that supports WPS.", __FUNCTION__);
#endif
		return -1;
	}

#if ENROLLEE_DEBUG
	WPS_PRINTF("%s: Found %d APs that support WPS.", __FUNCTION__, ap_num);
#endif

	if (mode == WPS_PIN_MODE) {
		DevicePasswordID = DPID_DEFAULT;
	}
	else if (mode == WPS_PBC_MODE) {
		DevicePasswordID = DPID_PUSHBUTTON;
	}
	
	for (i = 0; i < ap_num; i++) {
		bConfigured = 0;
		b1 = 0;
		b2 = 0;
		bDPIDExistButUnmatch = 0;

		ap = &ap_array[i];

#if ENROLLEE_DEBUG
		WPS_PRINTF("%s: Check AP(ssid=\"%s\")", __FUNCTION__, ap->ssid);
#endif

		if (mode == WPS_PIN_MODE && is_pin_ap_tried(ap)) {
#if ENROLLEE_DEBUG
			WPS_PRINTF("%s: PIN tried, can not choose.", __FUNCTION__);
#endif
			continue;
		}

		dataLen = ap->wpsIE.length - 4;
		p = ap->wpsIE.data;

#if ENROLLEE_DEBUG
		PrintHex(p, 64);////Debug
#endif

		if (WPS_get_word(p) != WPS_h2n16(E_Version_ID) 
			|| WPS_get_word(p+2) != WPS_h2n16(E_Version_Length) 
			|| *(p+4) != WPS_VERSION) {
#if ENROLLEE_DEBUG
			WPS_PRINTF("%s: Version is invalid\n", __FUNCTION__);
#endif
			continue;
		}
		else {
			p += 2+2+E_Version_Length;
		}

		/* For Buffalo AP and Corega AP, the order of the following Elements is random, it's not comply with the wifi-spec */
		while (((int)p - (int)&(ap->wpsIE.data[0])) < dataLen) {

			if (WPS_get_word(p) == WPS_h2n16(E_SimpleConfigState_ID) 
				&& WPS_get_word(p+2) == WPS_h2n16(E_SimpleConfigState_Length)) {

				if (*(p+4) == SIMPLE_CONFIG_STATE_CONFIGURED) {
					bConfigured = 1;
				}
				p += 2+2+E_SimpleConfigState_Length;
			}

			if (WPS_get_word(p) == WPS_h2n16(E_SelectedRegistrar_ID) 
				&& WPS_get_word(p+2) == WPS_h2n16(E_SelectedRegistrar_Length)) {
				if (*(p+4) != 1) {
#if ENROLLEE_DEBUG
					WPS_PRINTF("%s: SelectedRegistrar is invalid\n", __FUNCTION__);
#endif
				}
				else {
					b1 = 1;
				}
				p += 2+2+E_SelectedRegistrar_Length;
			}
			else if (WPS_get_word(p) == WPS_h2n16(E_DevicePasswordID_ID) 
				&& WPS_get_word(p+2) == WPS_h2n16(E_DevicePasswordID_Length)) {

				if (WPS_get_word(p+4) != WPS_h2n16(DevicePasswordID)) {
#if ENROLLEE_DEBUG
					WPS_PRINTF("%s: DevicePasswordID is invalid, 0x%x:0x%x\n", __FUNCTION__, WPS_n2h16(WPS_get_word(p+4)), DevicePasswordID);
#endif
					bDPIDExistButUnmatch = 1;
				}
				else {
					b2 = 1;
				}
				p += 2+2+E_DevicePasswordID_Length;
			}
			else {
				p += 2+2+WPS_n2h16(WPS_get_word(p+2));
			}
		}
#if ENROLLEE_DEBUG
		WPS_PRINTF("isConfigured=%d\n", bConfigured);
		WPS_PRINTF("SelectedRegistrar Match: %d\n", b1);
		WPS_PRINTF("DevicePasswordID Match: %d\n", b2);
#endif

		if (mode == WPS_PIN_MODE && !bDPIDExistButUnmatch) {
			retIndex = i;
			n ++;
		}
		else if (b1 && b2) {
			retIndex = i;
			n ++;
		}
	}
	
#if ENROLLEE_DEBUG
	WPS_PRINTF("%s: %d wps bss found!!!!!!\n\n", __FUNCTION__, n);
#endif

	if (mode == WPS_PIN_MODE) {
		if (n >= 1) {
			*selected_ap = ap_array[retIndex];
			add_tried_pin_ap_queue(selected_ap);
			return 0;
		}
		else {
			return -1;
		}
	}
	else if (mode == WPS_PBC_MODE) {
		if (n == 1) {
			*selected_ap = ap_array[retIndex];
			return 0;
		}
		else if (n == 0) {
			return -1;
		}
		else {
			return -2;
		}
	}
}

static void wps_enrol_thread_fn(void)
{
	int ret;
	WPS_u8 event;
	WPS_AP_DESC ap;
	
	while (1)
	{
		WPS_WaitSemaphore(wps_enrol_sem);
		wps_running = 1;
		
		WPS_PRINTF("Debug: %s - %s() - %d", __FILE__, __FUNCTION__, __LINE__);////Debug
	
		for(;;) {
			ret = wps_enrol_select_ap(get_enrollee_mode(), &ap);
			if (ret == -2) {
				event = USER_CALLBACK_EVENT_OVERLAP;
				break;
			}
			else if (ret == 0) {
				if (Wlan_IsAssociated()) {
					Wlan_Disassociate();
				}
				Wlan_AddEapolListener(wps_eapol_callback);
				wps_assoc_and_wait_completion(&ap);
				for (;;) {
					if (enrollee_is_regprotocol_done(wps_enrol_ptr)) {
						if (enrollee_is_regprotocol_successful(wps_enrol_ptr)) {
							event = USER_CALLBACK_EVENT_SUCCESS;
						}
						else {
							event = USER_CALLBACK_EVENT_ERROR;
						}
						break;
					}
					if (wps_enrol_stop_flag) {
						event = USER_CALLBACK_EVENT_STOPPED;
						break;
					}
					WPS_Sleep(500);
				}
				wps_disassoc_and_wait_completion();
				Wlan_RemoveEapolListener();
				if (event == USER_CALLBACK_EVENT_SUCCESS || event == USER_CALLBACK_EVENT_STOPPED) {
					break;
				}
			}
			else if (ret == -1) {
				if (WPS_GetSysTime() - wps_start_time >= wps_timeout_value) {
					event = USER_CALLBACK_EVENT_ERROR;
					break;
				}
				
				if (wps_enrol_stop_flag) {
					event = USER_CALLBACK_EVENT_STOPPED;
					break;
				}				
				empty_tried_pin_ap_queue();
			}
		} /* for(;;) */
		
		empty_tried_pin_ap_queue();
		wps_enrol_callback(event);		
		wps_running = 0;
	} /* while (1) */
}

int wps_enrol_initialize(void)
{	WPS_osfunc_init();
	wps_enrol_mode = WPS_DISABLED;
	WPS_STR_NCPY(wps_enrol_pin, "", sizeof(wps_enrol_pin));
	wps_enrol_callback = NULL;
	wps_enrol_sem = WPS_CreateSemaphore(1);
	if (wps_enrol_sem == NULL) {
		return WPS_ERROR_NO_MEM;
	}
	wps_enrol_thread = WPS_CreateThread(wps_enrol_thread_fn);
	if (wps_enrol_thread == NULL) {
		WPS_DeleteSemaphore(wps_enrol_sem);
		wps_enrol_sem = NULL;
		return WPS_ERROR_NO_MEM;
	}
	enrollee_create_instance(&wps_enrol_ptr);
	if (wps_enrol_ptr == NULL) {
		WPS_DeleteSemaphore(wps_enrol_sem);
		wps_enrol_sem = NULL;
		WPS_DeleteThread(wps_enrol_thread);
		wps_enrol_thread = NULL;
		return WPS_ERROR_NO_MEM;
	}
	return WPS_ERROR_SUCCESS;
}

int wps_enrol_set_mode(WPS_u8 mode)
{
	if (mode != WPS_PIN_MODE && mode != WPS_PBC_MODE) {
		return WPS_ERROR_INVALID_PARAM;
	}
	wps_enrol_mode = mode;
	return WPS_ERROR_SUCCESS;
}

int wps_enrol_set_pin(WPS_char *pin)
{
	if (pin == NULL || WPS_STR_LEN(pin) != 8) {
		return WPS_ERROR_INVALID_PARAM;
	}
	
	WPS_STR_NCPY(wps_enrol_pin, pin, sizeof(wps_enrol_pin));
	return WPS_ERROR_SUCCESS;
}

int wps_enrol_set_callback(WPS_USER_CALLBACK callback)
{
	if (callback == NULL) {
		return WPS_ERROR_INVALID_PARAM;
	}
	
	wps_enrol_callback = callback;
	return WPS_ERROR_SUCCESS;
}

int wps_enrol_start(void)
{
	if (wps_running != 0) {
		return WPS_ERROR_ALREADY_STARTED;
	}
	
	if (wps_enrol_mode == WPS_DISABLED) {
		return WPS_ERROR_MODE_NOT_SET;
	}
	
	if (wps_enrol_mode == WPS_PBC_MODE) {
		WPS_STR_NCPY(wps_enrol_pin, "00000000", sizeof(wps_enrol_pin));
	}
	
	if (WPS_STR_CMP(wps_enrol_pin, "") == 0) {
		return WPS_ERROR_PIN_NOT_SET;
	}
	
	if (wps_enrol_callback == NULL) {
		return WPS_ERROR_CALLBACK_NOT_SET;
	}
	
	wps_start_time = WPS_GetSysTime();
	wps_timeout_value = WPS_OVERALL_TIMEOUT * 1000;
	
	wps_enrol_stop_flag = 0;
	WPS_PostSemaphore(wps_enrol_sem);
	return WPS_ERROR_SUCCESS;
}

int wps_enrol_stop(void)
{
	if (wps_running != 1) {
		return WPS_ERROR_ALREADY_STOPPED;
	}
	wps_enrol_stop_flag = 1;
	return WPS_ERROR_SUCCESS;
}

int wps_enrol_get_wlan_param(USER_WLAN_PARAM *param)
{
	ENROLLEE_CREDENTIAL *p;

	if (param == NULL) {
		return WPS_ERROR_INVALID_PARAM;
	}
	
	if (wps_enrol_ptr == NULL ||
		!enrollee_is_regprotocol_successful(wps_enrol_ptr)) {
		return WPS_ERROR_NO_WLAN_PARAM;
	}

	p = &wps_enrol_ptr->credential;
	WPS_MEM_CPY(param->param_SSID, p->Cre_SSID, SSID_MAXLENGTH);
	param->param_SSID_Length = p->Cre_SSID_Length;
	param->param_AuthenticationType = p->Cre_AuthenticationType;
	param->param_EncryptionType = p->Cre_EncryptionType;
	param->param_NetworkKeyIndex = p->Cre_NetworkKeyIndex;
	WPS_MEM_CPY(param->param_NetworkKey, p->Cre_NetworkKey, NETWORKKEY_MAXLENGTH);
	param->param_NetworkKey_Length = p->Cre_NetworkKey_Length;	
	return WPS_ERROR_SUCCESS;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -