Step 3: Trying WPA

Top  Previous  Next

This and other projects in the Code Examples section are published on our website under the name "test_wln_lib".

 

OK then, now let's try to associate with an access point configured for WPA2-PSK security. Your can try WPA-PSK by yourself.

 

note_tip-wt

If your access point is configured for WPA-PSK/WPA2-PSK mode, select WPA2 on the device side.

 

With WPA, things get a bit tricker because of a pre-shared master key (PMK). This is the actual password used between your device and the access point. The key is calculated from a "human" password (that you define) and the access point's SSID (name). Wln_wpa_mkey_get() does the math. The bad news is that it takes 2 minutes... yep, sorry, 8000 iterations involving sha1 need that long. The good news is that you only need to do this once after changing the password or SSID. You can then just save the resulting key for the future use. STG library comes handy for this.

Our project now has a new function — connect_to_ap() — that calls wln_start(). This function takes all the same arguments as wln_start(). Connect_to_ap() stores the SSID, human password, and pre-shared master key into the EEPROM.  Wln_wpa_mkey_get() is only called if the SSID or human password change, or if the "PMK" setting is invalid. For the "PMK" setting to be valid, it must contain a 32-character string — the PMK always has this length. Keeping the PMK in the EEPROM allows us to avoid recalculating it — a huge time saver. Callback_wln_mkey_progress_update() is called repeatedly from within wln_wpa_mkey_get() while the PMK calculation is in progress. We put pat.play there to assure the user that the system isn't dead.

 

Below is the debug output we've got when connecting to the access point named "TIBB1".

 

 

WLN> ---START---

WLN> ACTIVE SCAN for TIBB1

WLN> ASSOCIATE with TIBB1 (bssid: 192.63.14.197.236.216, ch: 11)

WLN> Pre-associated for WPA1-PSK or WPA2-PSK, starting handshake process

WLN> Pairwise handshake, process step 1 of 4

WLN> Pairwise handshake, process step 2 of 4

WLN> Pairwise handshake, process step 3 of 4

WLN> Pairwise handshake, process step 4 of 4

WLN> ---OK(associated in WPA2-PSK mode)---

 

 

note_warning-wt

Some access points, notably CISCO devices, are so impatient during the WPA1/WPA2 handshaking process, that printing debug info makes them timeout. If you notice that the WLN library is stuck in the endless association loop, and you are sure that your password is set correctly, then try disabling debug printing! It may be the reason why the association fails.

 

The new iteration of our project is listed below. Notice how we set #define WLN_WPA 1 in global.tbh. This is necessary to enable WPA support.

We show one more trick in this example. Instead of having a listening TCP socket, we have a loopback socket that connects to a certain destination IP whenever there is a successful association. To ensure persistent connection, we put a polling code into on_sys_timer. Not the most beautiful of solutions, but gets the job done. The TCP connection is discarded whenever we get callback_wln_failiure().

 

note_tip-wt

Test outgoing connections by setting sock.targetip to your PC's address and using our I/O NINJA terminal/sniffer software. This software has a unique Listener Socket plugin that will allow your PC to receive incoming TCP connections.

 

global.tbh:

 

'DEFINES-------------------------------------------------------------

#define WLN_DEBUG_PRINT 1

#define WLN_WPA 1

 

#if PLATFORM_ID=EM500 or PLATFORM_ID=EM500W

 #define WLN_RESET_MODE 1 'there will be no dedicated reset, and all other lines are fixed

#elif PLATFORM_ID=EM1206 or PLATFORM_ID=EM1206W

 #define WLN_CLK PL_IO_NUM_14

 #define WLN_CS PL_IO_NUM_15

 #define WLN_DI PL_IO_NUM_12

 #define WLN_DO PL_IO_NUM_13

 #define WLN_RST PL_IO_NUM_11

#else

 'EM1000, NB1010,...

 #define WLN_CLK PL_IO_NUM_53

 #define WLN_CS PL_IO_NUM_49

 #define WLN_DI PL_IO_NUM_52

 #define WLN_DO PL_IO_NUM_50

 #define WLN_RST PL_IO_NUM_51

#endif

 

'INCLUDES------------------------------------------------------------

include "sock\trunk\sock.tbh" 'this lib is necessary for the WLN lib's operation

include "settings\trunk\settings.tbh" 'this lib is necessary to save pre-shared master key

includepp "settings.xtxt"

include "wln\trunk\wln.tbh"

 

'DECLARATIONS--------------------------------------------------------

declare function connect_to_ap(byref ap_name as string, security_mode as pl_wln_security_modes, byref key as string, domain as pl_wln_domains) as en_wln_status_codes

declare tcp_sock as byte

 

 

main.tbs:

 

include "global.tbh"

 

dim tcp_sock as byte

 

'====================================================================

sub on_sys_init()

 wln.ip="192.168.1.50"                                                '<--- set suitable IP here

 

 stg_start()

 

 if connect_to_ap("TIBB1",WLN_SECURITY_MODE_WPA2,"12345678",PL_WLN_DOMAIN_FCC)<>WLN_STATUS_OK then

         sys.halt

 end if

 

 'configure loopback socket

 tcp_sock=sock_get("TCP")

 sock.num=tcp_sock

 sock.rxbuffrq(1)

 sock.txbuffrq(1)

 sys.buffalloc

 sock.protocol=PL_SOCK_PROTOCOL_TCP

 sock.targetinterface=PL_SOCK_INTERFACE_WLN

 sock.targetip="192.168.1.67"                                '<----- set suitable target IP here

 sock.targetport=1000                                                '<----- set suitable target port here

end sub

 

'--------------------------------------------------------------------

sub on_sys_timer()

 wln_proc_timer()

 

 'this code ensures persistent connection to the target IP

 if wln_check_association()=PL_WLN_ASSOCIATED then

         sock.num=tcp_sock

         if sock.statesimple=PL_SSTS_CLOSED then

                 sock.connect

         end if

 end if

end sub

 

'--------------------------------------------------------------------

sub on_sock_data_arrival()

 wln_proc_data()

 

 'loopback tcp data

 if sock.num=tcp_sock then

         sock.setdata(sock.getdata(sock.txfree))

         sock.send

 end if

end sub

 

'--------------------------------------------------------------------

sub on_wln_task_complete(completed_task as pl_wln_tasks)

 wln_proc_task_complete(completed_task)

end sub

 

'--------------------------------------------------------------------

sub on_wln_event(wln_event as pl_wln_events)

 wln_proc_event(wln_event)

end sub

 

 

device.tbs:

 

include "global.tbh"

 

'====================================================================

function connect_to_ap(byref ap_name as string, security_mode as pl_wln_security_modes, byref key as string, domain as pl_wln_domains) as en_wln_status_codes

 dim pmk as string(32)

 

 #if WLN_WPA

         if security_mode=WLN_SECURITY_MODE_WPA1 or security_mode=WLN_SECURITY_MODE_WPA2 then

                 if stg_get("APN",0)<>ap_name or stg_get("PW",0)<>key or stg_sg("PMK",0,pmk,EN_STG_GET)<>EN_STG_STATUS_OK then

                         'recalculate the key

                         pmk=wln_wpa_mkey_get(key,ap_name)

                         stg_set("PMK",0,pmk)

                         stg_set("APN",0,ap_name)

                         stg_set("PW",0,key)

                 else

                         pmk=stg_get("PMK",0) 'the key stays the same

                 end if

         else

                 pmk=key

         end if

 #else

         pmk=key

 #endif

 

 connect_to_ap=wln_start(ap_name,security_mode,pmk,domain)

end function

 

'--------------------------------------------------------------------

sub callback_wln_ok()

 pat.play("G~",PL_PAT_CANINT)

end sub

 

'--------------------------------------------------------------------

sub callback_wln_failure(wln_state as en_wln_status_codes)

 pat.play("-",PL_PAT_CANINT)

 sock.num=tcp_sock

 sock.discard

end sub

 

'--------------------------------------------------------------------

sub callback_wln_pre_buffrq(required_buff_pages as byte)

end sub

 

'--------------------------------------------------------------------

sub callback_wln_rescan_result(current_rssi as byte, scan_rssi as byte, different_ap as no_yes)

end sub

 

'--------------------------------------------------------------------

sub callback_wln_mkey_progress_update(progress as byte)

 pat.play("B-**",PL_PAT_CANINT)

end sub

 

'--------------------------------------------------------------------

sub callback_stg_error(byref stg_name_or_num as string,index as byte,status as en_stg_status_codes)

end sub

 

'--------------------------------------------------------------------

sub callback_stg_pre_get(byref stg_name_or_num as string,index as byte,byref stg_value as string)

end sub

 

'--------------------------------------------------------------------

sub callback_stg_post_set(byref stg_name_or_num as string, index as byte,byref stg_value as string)

end sub

 

 

settings.xtxt (the underlying configuration file):

 

>>APN        E        S        1        0        32        A        ^                                        Access point name

>>PW        E        S        1        0        32        A        ^                                        Password

>>PMK        E        S        1        32        32        A        12345678901234567890123456789012        Pre-shared master key

 

#define STG_DESCRIPTOR_FILE "settings.xtxt"

#define STG_MAX_NUM_SETTINGS 3

#define STG_MAX_SETTING_NAME_LEN 3

#define STG_MAX_SETTING_VALUE_LEN 32