WINC: Add support for AP mode.

This commit is contained in:
iabdalkader 2017-03-09 20:39:53 +02:00
parent 32dded64fd
commit a4561c7efa
2 changed files with 258 additions and 42 deletions

View File

@ -15,12 +15,14 @@
#include "py/objlist.h"
#include "py/stream.h"
#include "py/runtime.h"
#include "lib/netutils/netutils.h"
#include "modnetwork.h"
#include "pin.h"
#include "genhdr/pins.h"
#include "spi.h"
#include "pybioctl.h"
#include "common.h"
#include "py_helper.h"
// WINC's includes
#include "driver/include/nmasic.h"
@ -47,6 +49,7 @@
static volatile bool ip_obtained = false;
static volatile bool wlan_connected = false;
static volatile uint32_t connected_sta_ip = false;
static void *async_request_data;
static uint8_t async_request_type=0;
@ -62,6 +65,13 @@ typedef struct {
struct sockaddr_in addr;
} accept_t;
typedef enum {
WINC_MODE_STA,
WINC_MODE_AP,
WINC_MODE_P2P,
WINC_MODE_FIRMWARE,
}winc_mode_t;
/**
* DNS Callback.
*
@ -212,7 +222,7 @@ static void socket_callback(SOCKET sock, uint8_t msg_type, void *msg)
}
/**
* WiFi Callback.
* WiFi Callback in AP mode.
*
* msg_type: type of Wi-Fi notification. Possible types are:
* M2M_WIFI_RESP_CON_STATE_CHANGED
@ -236,7 +246,63 @@ static void socket_callback(SOCKET sock, uint8_t msg_type, void *msg)
* msg: A pointer to a buffer containing the notification parameters (if any).
* It should be casted to the correct data type corresponding to the notification type.
*/
static void wifi_callback(uint8_t msg_type, void *msg)
static void wifi_callback_ap(uint8_t msg_type, void *msg)
{
switch (msg_type) {
case M2M_WIFI_RESP_CON_STATE_CHANGED: {
tstrM2mWifiStateChanged *wifi_state = (tstrM2mWifiStateChanged *)msg;
if (wifi_state->u8CurrState == M2M_WIFI_CONNECTED) {
debug_printf("Station connected\r\n");
} else if (wifi_state->u8CurrState == M2M_WIFI_DISCONNECTED) {
connected_sta_ip = 0;
debug_printf("Station disconnected\r\n");
}
break;
}
case M2M_WIFI_REQ_DHCP_CONF: {
uint8_t *ip = (uint8_t *)msg;
debug_printf("Station connected. IP is %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3]);
((uint8_t*) &connected_sta_ip)[0] = ip[0];
((uint8_t*) &connected_sta_ip)[1] = ip[1];
((uint8_t*) &connected_sta_ip)[2] = ip[2];
((uint8_t*) &connected_sta_ip)[3] = ip[3];
break;
}
default:
debug_printf("Unknown message type: %d\n", msg_type);
break;
}
}
/**
* WiFi Callback in STA mode.
*
* msg_type: type of Wi-Fi notification. Possible types are:
* M2M_WIFI_RESP_CON_STATE_CHANGED
* M2M_WIFI_RESP_CONN_INFO
* M2M_WIFI_REQ_DHCP_CONF
* M2M_WIFI_REQ_WPS
* M2M_WIFI_RESP_IP_CONFLICT
* M2M_WIFI_RESP_SCAN_DONE
* M2M_WIFI_RESP_SCAN_RESULT
* M2M_WIFI_RESP_CURRENT_RSSI
* M2M_WIFI_RESP_CLIENT_INFO
* M2M_WIFI_RESP_PROVISION_INFO
* M2M_WIFI_RESP_DEFAULT_CONNECT
*
* In case Bypass mode is defined :
* M2M_WIFI_RESP_ETHERNET_RX_PACKET
*
* In case Monitoring mode is used:
* M2M_WIFI_RESP_WIFI_RX_PACKET
*
* msg: A pointer to a buffer containing the notification parameters (if any).
* It should be casted to the correct data type corresponding to the notification type.
*/
static void wifi_callback_sta(uint8_t msg_type, void *msg)
{
// Index of scan list to request scan result.
static uint8_t scan_request_index = 0;
@ -251,11 +317,11 @@ static void wifi_callback(uint8_t msg_type, void *msg)
}
case M2M_WIFI_RESP_CON_STATE_CHANGED: {
tstrM2mWifiStateChanged *pstrWifiState = (tstrM2mWifiStateChanged *)msg;
if (pstrWifiState->u8CurrState == M2M_WIFI_CONNECTED) {
tstrM2mWifiStateChanged *wifi_state = (tstrM2mWifiStateChanged *)msg;
if (wifi_state->u8CurrState == M2M_WIFI_CONNECTED) {
wlan_connected = true;
m2m_wifi_request_dhcp_client();
} else if (pstrWifiState->u8CurrState == M2M_WIFI_DISCONNECTED) {
} else if (wifi_state->u8CurrState == M2M_WIFI_DISCONNECTED) {
ip_obtained = false;
wlan_connected = false;
async_request_done = true;
@ -630,30 +696,47 @@ typedef struct _winc_obj_t {
static const winc_obj_t winc_obj = {{(mp_obj_type_t*)&mod_network_nic_type_winc}};
// Initialise the module using the given SPI bus and pins and return a winc object.
static mp_obj_t winc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args)
static mp_obj_t winc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args)
{
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 1, false);
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = WINC_MODE_STA } },
};
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), allowed_args, args);
// get mode
winc_mode_t winc_mode = args[0].u_int;
// Initialize the BSP.
nm_bsp_init();
// Firmware update enabled
if (n_args && mp_obj_get_int(args[0]) == true) {
switch (winc_mode) {
case WINC_MODE_FIRMWARE: {
// Enter download mode.
printf("Enabling download mode...\n");
printf("Running in Firmware Upgrade mode...\n");
if (m2m_wifi_download_mode() != M2M_SUCCESS) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to enter download mode!"));
}
} else {
// Initialize Wi-Fi parameters structure.
break;
}
case WINC_MODE_AP:
case WINC_MODE_STA: {
tstrWifiInitParam param;
// Initialize Wi-Fi parameters structure.
memset((uint8_t *)&param, 0, sizeof(tstrWifiInitParam));
param.pfAppWifiCb = wifi_callback;
if (winc_mode == WINC_MODE_AP) {
param.pfAppWifiCb = wifi_callback_ap;
} else {
param.pfAppWifiCb = wifi_callback_sta;
}
// Initialize Wi-Fi driver with data and status callbacks.
int ret = m2m_wifi_init(&param);
if (M2M_SUCCESS != ret) {
if (m2m_wifi_init(&param) != M2M_SUCCESS) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "failed to init WINC1500 module"));
}
@ -678,6 +761,21 @@ static mp_obj_t winc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_ui
// Register with network module
mod_network_register_nic((mp_obj_t)&winc_obj);
if (winc_mode == WINC_MODE_AP) {
printf("Running in Access Point mode...\n");
} else {
printf("Running in Station mode...\n");
}
break;
}
case WINC_MODE_P2P:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "P2P mode is not supported yet!"));
break;
default:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "WiFi mode is not supported!"));
}
return (mp_obj_t)&winc_obj;
@ -722,6 +820,67 @@ static mp_obj_t winc_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
return mp_const_none;
}
// method start_ap(ssid, key=None, security=OPEN)
static mp_obj_t winc_start_ap(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
{
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_ssid, MP_ARG_REQUIRED| MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = M2M_WIFI_SEC_OPEN } }, //M2M_WIFI_SEC_WPA_PSK
{ MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get ssid
mp_uint_t ssid_len;
const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len);
// get key and security
mp_uint_t key_len = 0;
const char *key = NULL;
mp_uint_t security = args[2].u_int;
if (security != M2M_WIFI_SEC_OPEN && security != M2M_WIFI_SEC_WEP) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "AP mode supports WEP security only."));
}
if (security == M2M_WIFI_SEC_WEP && args[1].u_obj == MP_OBJ_NULL) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Missing WEP key!"));
}
key = mp_obj_str_get_data(args[1].u_obj, &key_len);
// get channel
mp_uint_t channel = args[3].u_int;
tstrM2MAPConfig apconfig;
memset(&apconfig, 0, sizeof(tstrM2MAPConfig));
strcpy((char *)&apconfig.au8SSID, ssid);
apconfig.u8ListenChannel = channel;
apconfig.u8SecType = security;
apconfig.au8DHCPServerIP[0] = 192;
apconfig.au8DHCPServerIP[1] = 168;
apconfig.au8DHCPServerIP[2] = 1;
apconfig.au8DHCPServerIP[3] = 1;
if (security != M2M_WIFI_SEC_OPEN) {
strcpy((char *)&apconfig.au8WepKey, key);
apconfig.u8KeySz = WEP_40_KEY_STRING_SIZE;
apconfig.u8KeyIndx = 1;
}
// Initialize WiFi in AP mode.
if (m2m_wifi_enable_ap(&apconfig) != M2M_SUCCESS) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "failed to start in AP mode"));
}
printf("AP mode started. You can connect to %s.\r\n", ssid);
return mp_const_none;
}
static mp_obj_t winc_disconnect(mp_obj_t self_in)
{
m2m_wifi_disconnect();
@ -733,6 +892,45 @@ static mp_obj_t winc_isconnected(mp_obj_t self_in)
return mp_obj_new_bool(wlan_connected && ip_obtained);
}
static mp_obj_t winc_connected_sta(mp_obj_t self_in)
{
mp_obj_t sta_list = mp_obj_new_list(0, NULL);
if (connected_sta_ip == 0) {
m2m_wifi_handle_events(NULL);
}
if (connected_sta_ip != 0) {
mp_obj_list_append(sta_list, netutils_format_inet_addr(
(uint8_t*)&connected_sta_ip, 0, NETUTILS_BIG));
}
return sta_list;
}
static mp_obj_t winc_wait_for_sta(mp_obj_t self_in, mp_obj_t timeout_in)
{
// get timeout
mp_obj_t sta_list = mp_obj_new_list(0, NULL);
mp_uint_t timeout = mp_obj_get_int(timeout_in);
uint32_t tick_start = HAL_GetTick();
while (connected_sta_ip == 0) {
// Handle pending events from network controller.
m2m_wifi_handle_events(NULL);
if (timeout && ((HAL_GetTick() - tick_start) >= timeout)) {
break;
}
}
if (connected_sta_ip != 0) {
mp_obj_list_append(sta_list, netutils_format_inet_addr(
(uint8_t*)&connected_sta_ip, 0, NETUTILS_BIG));
}
return sta_list;
}
static mp_obj_t winc_ifconfig(mp_obj_t self_in)
{
mp_obj_t info_list;
@ -843,8 +1041,11 @@ static mp_obj_t winc_fw_update(mp_obj_t self_in)
}
static MP_DEFINE_CONST_FUN_OBJ_KW(winc_connect_obj, 1, winc_connect);
static MP_DEFINE_CONST_FUN_OBJ_KW(winc_start_ap_obj,1, winc_start_ap);
static MP_DEFINE_CONST_FUN_OBJ_1(winc_disconnect_obj, winc_disconnect);
static MP_DEFINE_CONST_FUN_OBJ_1(winc_isconnected_obj, winc_isconnected);
static MP_DEFINE_CONST_FUN_OBJ_1(winc_connected_sta_obj,winc_connected_sta);
static MP_DEFINE_CONST_FUN_OBJ_2(winc_wait_for_sta_obj, winc_wait_for_sta);
static MP_DEFINE_CONST_FUN_OBJ_1(winc_ifconfig_obj, winc_ifconfig);
static MP_DEFINE_CONST_FUN_OBJ_1(winc_scan_obj, winc_scan);
static MP_DEFINE_CONST_FUN_OBJ_1(winc_rssi_obj, winc_rssi);
@ -854,8 +1055,11 @@ static MP_DEFINE_CONST_FUN_OBJ_1(winc_fw_update_obj, winc_fw_update);
static const mp_map_elem_t winc_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&winc_connect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_start_ap), (mp_obj_t)&winc_start_ap_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&winc_disconnect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&winc_isconnected_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_connected_sta), (mp_obj_t)&winc_connected_sta_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wait_for_sta), (mp_obj_t)&winc_wait_for_sta_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&winc_ifconfig_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&winc_scan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rssi), (mp_obj_t)&winc_rssi_obj },
@ -867,6 +1071,11 @@ static const mp_map_elem_t winc_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_WEP), MP_OBJ_NEW_SMALL_INT(M2M_WIFI_SEC_WEP) }, // Security type WEP (40 or 104) OPEN OR SHARED.
{ MP_OBJ_NEW_QSTR(MP_QSTR_WPA_PSK), MP_OBJ_NEW_SMALL_INT(M2M_WIFI_SEC_WPA_PSK) }, // Network is secured with WPA/WPA2 personal(PSK).
{ MP_OBJ_NEW_QSTR(MP_QSTR_802_1X), MP_OBJ_NEW_SMALL_INT(M2M_WIFI_SEC_802_1X) }, // Network is secured with WPA/WPA2 Enterprise.
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_STA), MP_OBJ_NEW_SMALL_INT(WINC_MODE_STA) }, // Start in Staion mode.
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_AP), MP_OBJ_NEW_SMALL_INT(WINC_MODE_AP) }, // Start in Access Point mode.
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_P2P), MP_OBJ_NEW_SMALL_INT(WINC_MODE_P2P) }, // Start in Peer-to-Peer (WiFi Direct) mode.
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_FIRMWARE), MP_OBJ_NEW_SMALL_INT(WINC_MODE_FIRMWARE) }, // Start in Firmware Upgrade mode.
};
static MP_DEFINE_CONST_DICT(winc_locals_dict, winc_locals_dict_table);

View File

@ -281,8 +281,11 @@ Q(IPPROTO_RAW)
// for WINC1500 module
Q(WINC)
Q(connect)
Q(start_ap)
Q(disconnect)
Q(isconnected)
Q(connected_sta)
Q(wait_for_sta)
Q(ifconfig)
Q(fw_version)
Q(fw_dump)
@ -293,6 +296,10 @@ Q(OPEN)
Q(WEP)
Q(WPA_PSK)
Q(802_1X)
Q(MODE_STA)
Q(MODE_AP)
Q(MODE_P2P)
Q(MODE_FIRMWARE)
Q(ssid)
Q(key)
Q(security)