Commit 3bc77e88 authored by Gil Pitney's avatar Gil Pitney Committed by Anas Nashif
Browse files

net: drivers: wifi: SimpleLink WiFi Offload Driver (wifi_mgmt only)



Initiate a SimpleLink WiFi Driver, implemented to the WiFi management
offload APIs for scan, connect, disconnect.

Also registers the DHCP-obtained IPv4 address upon connect.

This was validated on a cc3220sf_launchxl using the wifi
shell module from the Zephyr shell_module sample.

Signed-off-by: default avatarGil Pitney <gil.pitney@linaro.org>
parent 7a864bb7
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
add_subdirectory_ifdef(CONFIG_WIFI_WINC1500	winc1500)
if(CONFIG_WIFI_SIMPLELINK)
  zephyr_include_directories(
    .
    $ENV{ZEPHYR_BASE}/ext/hal/ti/simplelink/kernel/zephyr/dpl
    $ENV{ZEPHYR_BASE}/ext/hal/ti/simplelink/source
    $ENV{ZEPHYR_BASE}/ext/hal/ti/simplelink/source/ti/drivers/net/wifi/porting
    $ENV{ZEPHYR_BASE}/ext/hal/ti/simplelink/source/ti/drivers/net/wifi/bsd
    )
  zephyr_sources(
    simplelink_support.c
    simplelink.c
    )
endif()
+1 −0
Original line number Diff line number Diff line
@@ -44,5 +44,6 @@ config WIFI_OFFLOAD
	  Enable support for Full-MAC WiFi devices.

source "drivers/wifi/winc1500/Kconfig.winc1500"
source "drivers/wifi/Kconfig.simplelink"

endif # WIFI
+46 −0
Original line number Diff line number Diff line
# Kconfig - SimpleLink WiFi driver options

#
# Copyright (c) 2018 Texas Instruments, Incorporated
#
# SPDX-License-Identifier: Apache-2.0
#

menuconfig WIFI_SIMPLELINK
	bool "SimpleLink WiFi driver support"
	default n
	depends on WIFI
	select SIMPLELINK_HOST_DRIVER
	select WIFI_OFFLOAD
	select NET_L2_WIFI_MGMT

if WIFI_SIMPLELINK

config WIFI_SIMPLELINK_NAME
	string "Driver name"
	default "SimpleLink"

config WIFI_SIMPLELINK_MAX_PACKET_SIZE
	int "Maximum size of a packet, in bytes"
	# MTU (ipv4) per: http://www.ti.com/lit/ug/swru455d/swru455d.pdf:
	default 1472
	help
	 Set the maximum size of a network packet going through the chip.
	 This sets the size of each buffer, in each buffer pool.
	 Do not modify it unless you know what you are doing.

config WIFI_SIMPLELINK_SCAN_COUNT
	int "Number of entries in network scan table: Max: 30"
	default 20
	help
	 The number of results to request on a wifi scan operation.
	 Actual number returned may be less.  Maximum is 30.

config WIFI_SIMPLELINK_MAX_SCAN_RETRIES
	int "Number of retries to get network scan table"
	default 10
	help
	 The number of times, separated by a one second interval, to retry
	 a request for the network list.

endif # WIFI_SIMPLELINK
+239 −0
Original line number Diff line number Diff line
/**
 * Copyright (c) 2018 Texas Instruments, Incorporated
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define SYS_LOG_LEVEL CONFIG_SYS_LOG_WIFI_LEVEL
#define SYS_LOG_DOMAIN "dev/simplelink"
#include <logging/sys_log.h>

#include <zephyr.h>
#include <kernel.h>
#include <device.h>
#include <net/net_if.h>
#include <net/wifi_mgmt.h>
#include <net/net_offload.h>

#include <ti/drivers/net/wifi/wlan.h>
#include "simplelink_support.h"

#define SCAN_RETRY_DELAY 2000  /* ms */

struct simplelink_data {
	struct net_if *iface;
	unsigned char mac[6];

	/* Fields for scan API to emulate an asynchronous scan: */
	struct k_delayed_work work;
	scan_result_cb_t cb;
	int num_results_or_err;
	int scan_retries;
};

static struct simplelink_data simplelink_data;

/* Handle connection events from the SimpleLink Event Handlers: */
static void simplelink_wifi_cb(u32_t event, struct sl_connect_state *conn)
{
	struct in_addr addr;
	struct in_addr gwaddr;
	int status;

	/*
	 * Once Zephyr wifi_mgmt wifi_status codes are defined, will need
	 * to map from SimpleLink error codes.  For now, just return -EIO.
	 */
	status = (conn->error ? -EIO : 0);

	switch (event) {
	case SL_WLAN_EVENT_CONNECT:
		/* Only get this event if connect succeeds: */
		wifi_mgmt_raise_connect_result_event(simplelink_data.iface,
						     status);
		break;

	case SL_WLAN_EVENT_DISCONNECT:
		/* Could be during a connect, disconnect, or async error: */
		wifi_mgmt_raise_disconnect_result_event(simplelink_data.iface,
							status);
		break;

	case SIMPLELINK_WIFI_CB_IPACQUIRED:
		addr.s_addr = htonl(conn->ip_addr);
		gwaddr.s_addr = htonl(conn->gateway_ip);
		net_if_ipv4_set_gw(simplelink_data.iface, &gwaddr);
		net_if_ipv4_addr_add(simplelink_data.iface, &addr,
				     NET_ADDR_DHCP, 0);
		break;

	default:
		SYS_LOG_DBG("Unrecognized mgmt event: 0x%x", event);
		break;
	}
}

/* TBD: Only here to link/test WiFi mgmnt part */
static struct net_offload simplelink_offload = {
	.get            = NULL,
	.bind		= NULL,
	.listen		= NULL,
	.connect	= NULL,
	.accept		= NULL,
	.send		= NULL,
	.sendto		= NULL,
	.recv		= NULL,
	.put		= NULL,
};

static void simplelink_scan_work_handler(struct k_work *work)
{
	if (simplelink_data.num_results_or_err > 0) {
		int index = 0;
		struct wifi_scan_result scan_result;

		/* Iterate over the table, and call the scan_result callback. */
		while (index < simplelink_data.num_results_or_err) {
			_simplelink_get_scan_result(index, &scan_result);
			simplelink_data.cb(simplelink_data.iface, 0,
					   &scan_result);
			/* Yield, to ensure notifications get delivered:  */
			k_yield();
			index++;
		}

		/* Sending a NULL entry indicates e/o results, and
		 * triggers the NET_EVENT_WIFI_SCAN_DONE event:
		 */
		simplelink_data.cb(simplelink_data.iface, 0, NULL);

	} else if ((simplelink_data.num_results_or_err ==
		    SL_ERROR_WLAN_GET_NETWORK_LIST_EAGAIN) &&
		   (simplelink_data.scan_retries++ <
		    CONFIG_WIFI_SIMPLELINK_MAX_SCAN_RETRIES)) {
		s32_t delay;

		/* Try again: */
		simplelink_data.num_results_or_err = _simplelink_start_scan();
		simplelink_data.scan_retries++;
		delay = (simplelink_data.num_results_or_err > 0 ? 0 :
			 SCAN_RETRY_DELAY);
		if (delay > 0) {
			SYS_LOG_DBG("Retrying scan...");
		}
		k_delayed_work_submit(&simplelink_data.work, delay);

	} else {
		/* Encountered an error, or max retries exceeded: */
		SYS_LOG_ERR("Scan failed: retries: %d; err: %d",
			    simplelink_data.scan_retries,
			    simplelink_data.num_results_or_err);
		simplelink_data.cb(simplelink_data.iface, -EIO, NULL);
	}
}

static int simplelink_mgmt_scan(struct device *dev, scan_result_cb_t cb)
{
	int err;
	int status;

	/* Cancel any previous scan processing in progress: */
	k_delayed_work_cancel(&simplelink_data.work);

	/* "Request" the scan: */
	err = _simplelink_start_scan();

	/* Now, launch a delayed work handler to do retries and reporting.
	 * Indicate (to the work handler) either a positive number of results
	 * already returned, or indicate a retry is required:
	 */
	if ((err > 0) || (err == SL_ERROR_WLAN_GET_NETWORK_LIST_EAGAIN)) {
		s32_t delay = (err > 0 ? 0 : SCAN_RETRY_DELAY);

		/* Store for later reference by delayed work handler: */
		simplelink_data.cb = cb;
		simplelink_data.num_results_or_err = err;
		simplelink_data.scan_retries = 0;

		k_delayed_work_submit(&simplelink_data.work, delay);
		status = 0;
	} else {
		status = -EIO;
	}

	return status;
}

static int simplelink_mgmt_connect(struct device *dev,
				   struct wifi_connect_req_params *params)
{
	int ret;

	ret = _simplelink_connect(params);

	return ret ? -EIO : ret;
}

static int simplelink_mgmt_disconnect(struct device *dev)
{
	int ret;

	ret = _simplelink_disconnect();

	return ret ? -EIO : ret;
}

static void simplelink_iface_init(struct net_if *iface)
{
	SYS_LOG_DBG("MAC Address %02X:%02X:%02X:%02X:%02X:%02X",
		    simplelink_data.mac[0], simplelink_data.mac[1],
		    simplelink_data.mac[2],
		    simplelink_data.mac[3], simplelink_data.mac[4],
		    simplelink_data.mac[5]);

	net_if_set_link_addr(iface, simplelink_data.mac,
			     sizeof(simplelink_data.mac),
			     NET_LINK_ETHERNET);

	/* TBD: Pending support for socket offload: */
	iface->if_dev->offload = &simplelink_offload;

	simplelink_data.iface = iface;
}

static const struct net_wifi_mgmt_offload simplelink_api = {
	.iface_api.init = simplelink_iface_init,
	.scan		= simplelink_mgmt_scan,
	.connect	= simplelink_mgmt_connect,
	.disconnect	= simplelink_mgmt_disconnect,
};

static int simplelink_init(struct device *dev)
{
	int ret;

	ARG_UNUSED(dev);

	/* Initialize and configure NWP to defaults: */
	ret = _simplelink_init(simplelink_wifi_cb);
	if (ret) {
		SYS_LOG_ERR("_simplelink_init failed!");
		return(-EIO);
	}

	/* Grab our MAC address: */
	_simplelink_get_mac(simplelink_data.mac);

	/* We use system workqueue to deal with scan retries: */
	k_delayed_work_init(&simplelink_data.work,
			    simplelink_scan_work_handler);

	SYS_LOG_DBG("SimpleLink driver Initialized");

	return 0;
}

NET_DEVICE_OFFLOAD_INIT(simplelink, CONFIG_WIFI_SIMPLELINK_NAME,
			simplelink_init, &simplelink_data, NULL,
			CONFIG_WIFI_INIT_PRIORITY, &simplelink_api,
			CONFIG_WIFI_SIMPLELINK_MAX_PACKET_SIZE);
+598 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading