2018-10-09 17:49:44 +02:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2018 Linaro
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
#define LOG_LEVEL CONFIG_WIFI_LOG_LEVEL
|
|
|
|
#include <logging/log.h>
|
|
|
|
LOG_MODULE_REGISTER(wifi_eswifi_core);
|
|
|
|
|
|
|
|
#include <zephyr.h>
|
|
|
|
#include <kernel.h>
|
|
|
|
#include <device.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
2019-06-25 15:53:52 -04:00
|
|
|
#include <drivers/gpio.h>
|
2018-10-09 17:49:44 +02:00
|
|
|
#include <net/net_pkt.h>
|
|
|
|
#include <net/net_if.h>
|
|
|
|
#include <net/net_context.h>
|
|
|
|
#include <net/net_offload.h>
|
|
|
|
#include <net/wifi_mgmt.h>
|
|
|
|
|
|
|
|
#include <net/ethernet.h>
|
|
|
|
#include <net_private.h>
|
|
|
|
#include <net/net_core.h>
|
|
|
|
#include <net/net_pkt.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2019-06-26 10:33:49 -04:00
|
|
|
#include <sys/printk.h>
|
2018-10-09 17:49:44 +02:00
|
|
|
|
|
|
|
#include "eswifi.h"
|
|
|
|
|
|
|
|
#define ESWIFI_WORKQUEUE_STACK_SIZE 1024
|
|
|
|
K_THREAD_STACK_DEFINE(eswifi_work_q_stack, ESWIFI_WORKQUEUE_STACK_SIZE);
|
|
|
|
|
|
|
|
static struct eswifi_dev eswifi0; /* static instance */
|
|
|
|
|
|
|
|
static int eswifi_reset(struct eswifi_dev *eswifi)
|
|
|
|
{
|
|
|
|
gpio_pin_write(eswifi->resetn.dev, eswifi->resetn.pin, 0);
|
|
|
|
k_sleep(10);
|
|
|
|
gpio_pin_write(eswifi->resetn.dev, eswifi->resetn.pin, 1);
|
|
|
|
gpio_pin_write(eswifi->wakeup.dev, eswifi->wakeup.pin, 1);
|
|
|
|
k_sleep(500);
|
|
|
|
|
|
|
|
/* fetch the cursor */
|
2019-01-07 18:40:02 +01:00
|
|
|
return eswifi_request(eswifi, NULL, 0, eswifi->buf,
|
|
|
|
sizeof(eswifi->buf));
|
2018-10-09 17:49:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline int __parse_ssid(char *str, char *ssid)
|
|
|
|
{
|
|
|
|
/* fnt => '"SSID"' */
|
|
|
|
|
|
|
|
if (!*str || (*str != '"')) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
str++;
|
|
|
|
while (*str && (*str != '"')) {
|
|
|
|
*ssid++ = *str++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ssid = '\0';
|
|
|
|
|
|
|
|
if (*str != '"') {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __parse_scan_res(char *str, struct wifi_scan_result *res)
|
|
|
|
{
|
|
|
|
int field = 0;
|
|
|
|
|
|
|
|
/* fmt => #001,"SSID",MACADDR,RSSI,BITRATE,MODE,SECURITY,BAND,CHANNEL */
|
|
|
|
|
|
|
|
while (*str) {
|
|
|
|
if (*str != ',') {
|
|
|
|
str++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!*++str) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (++field) {
|
|
|
|
case 1: /* SSID */
|
|
|
|
__parse_ssid(str, res->ssid);
|
|
|
|
res->ssid_length = strlen(res->ssid);
|
|
|
|
str += res->ssid_length;
|
|
|
|
break;
|
|
|
|
case 2: /* mac addr */
|
|
|
|
break;
|
|
|
|
case 3: /* RSSI */
|
|
|
|
res->rssi = atoi(str);
|
|
|
|
break;
|
|
|
|
case 4: /* bitrate */
|
|
|
|
break;
|
|
|
|
case 5: /* mode */
|
|
|
|
break;
|
|
|
|
case 6: /* security */
|
|
|
|
if (!strncmp(str, "Open", 4)) {
|
|
|
|
res->security = WIFI_SECURITY_TYPE_NONE;
|
|
|
|
} else {
|
|
|
|
res->security = WIFI_SECURITY_TYPE_PSK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 7: /* band */
|
|
|
|
break;
|
|
|
|
case 8: /* channel */
|
|
|
|
res->channel = atoi(str);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-21 16:00:56 +01:00
|
|
|
int eswifi_at_cmd_rsp(struct eswifi_dev *eswifi, char *cmd, char **rsp)
|
|
|
|
{
|
|
|
|
const char startstr[] = "\r\n";
|
|
|
|
const char endstr[] = "\r\nOK\r\n>";
|
|
|
|
int i, len, rsplen = -EINVAL;
|
|
|
|
|
|
|
|
len = eswifi_request(eswifi, cmd, strlen(cmd), eswifi->buf,
|
|
|
|
sizeof(eswifi->buf));
|
|
|
|
if (len < 0) {
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check response, format should be "\r\n[DATA]\r\nOK\r\n>"
|
|
|
|
* Data is in arbitrary format (not only ASCII)
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Check start characters */
|
|
|
|
if (strncmp(eswifi->buf, startstr, strlen(startstr))) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len < sizeof(endstr) - 1 + sizeof(startstr) - 1) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check end characters */
|
|
|
|
for (i = len - sizeof(endstr); i > 0; i--) {
|
|
|
|
if (!strncmp(&eswifi->buf[i], endstr, 7)) {
|
|
|
|
if (rsp) {
|
|
|
|
eswifi->buf[i] = '\0';
|
|
|
|
*rsp = &eswifi->buf[2];
|
|
|
|
rsplen = &eswifi->buf[i] - *rsp;
|
|
|
|
} else {
|
|
|
|
rsplen = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rsplen;
|
|
|
|
}
|
|
|
|
|
|
|
|
int eswifi_at_cmd(struct eswifi_dev *eswifi, char *cmd)
|
|
|
|
{
|
|
|
|
return eswifi_at_cmd_rsp(eswifi, cmd, NULL);
|
|
|
|
}
|
|
|
|
|
2018-10-09 17:49:44 +02:00
|
|
|
struct eswifi_dev *eswifi_by_iface_idx(u8_t iface)
|
|
|
|
{
|
|
|
|
/* only one instance */
|
|
|
|
LOG_DBG("%d", iface);
|
|
|
|
return &eswifi0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __parse_ipv4_address(char *str, char *ssid, u8_t ip[4])
|
|
|
|
{
|
|
|
|
unsigned int byte = -1;
|
|
|
|
|
|
|
|
/* fmt => [JOIN ] SSID,192.168.2.18,0,0 */
|
|
|
|
while (*str) {
|
|
|
|
if (byte == -1) {
|
|
|
|
if (!strncmp(str, ssid, strlen(ssid))) {
|
2018-11-29 11:12:22 -08:00
|
|
|
byte = 0U;
|
2018-10-09 17:49:44 +02:00
|
|
|
str += strlen(ssid);
|
|
|
|
}
|
|
|
|
str++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
ip[byte++] = atoi(str);
|
|
|
|
while (*str && (*str++ != '.')) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-12-21 16:00:56 +01:00
|
|
|
static void eswifi_scan(struct eswifi_dev *eswifi)
|
2018-10-09 17:49:44 +02:00
|
|
|
{
|
|
|
|
char cmd[] = "F0\r";
|
2018-12-21 16:00:56 +01:00
|
|
|
char *data;
|
|
|
|
int i, ret;
|
2018-10-09 17:49:44 +02:00
|
|
|
|
|
|
|
LOG_DBG("");
|
|
|
|
|
|
|
|
eswifi_lock(eswifi);
|
|
|
|
|
2018-12-21 16:00:56 +01:00
|
|
|
ret = eswifi_at_cmd_rsp(eswifi, cmd, &data);
|
|
|
|
if (ret < 0) {
|
|
|
|
eswifi->scan_cb(eswifi->iface, -EIO, NULL);
|
2018-10-09 17:49:44 +02:00
|
|
|
eswifi_unlock(eswifi);
|
2018-12-21 16:00:56 +01:00
|
|
|
return;
|
2018-10-09 17:49:44 +02:00
|
|
|
}
|
|
|
|
|
2018-12-21 16:00:56 +01:00
|
|
|
for (i = 0; i < ret; i++) {
|
|
|
|
if (data[i] == '#') {
|
2018-10-09 17:49:44 +02:00
|
|
|
struct wifi_scan_result res = {0};
|
|
|
|
|
2018-12-21 16:00:56 +01:00
|
|
|
__parse_scan_res(&data[i], &res);
|
2018-10-09 17:49:44 +02:00
|
|
|
|
|
|
|
eswifi->scan_cb(eswifi->iface, 0, &res);
|
|
|
|
k_yield();
|
|
|
|
|
2019-06-04 10:52:23 -04:00
|
|
|
while (data[i] && data[i] != '\n') {
|
2018-10-09 17:49:44 +02:00
|
|
|
i++;
|
2019-06-04 10:52:23 -04:00
|
|
|
}
|
2018-10-09 17:49:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eswifi_connect(struct eswifi_dev *eswifi)
|
|
|
|
{
|
|
|
|
char connect[] = "C0\r";
|
|
|
|
struct in_addr addr;
|
2018-12-21 16:00:56 +01:00
|
|
|
char *rsp;
|
2018-10-09 17:49:44 +02:00
|
|
|
int err;
|
|
|
|
|
|
|
|
LOG_DBG("Connecting to %s (pass=%s)", eswifi->sta.ssid,
|
|
|
|
eswifi->sta.pass);
|
|
|
|
|
|
|
|
eswifi_lock(eswifi);
|
|
|
|
|
|
|
|
/* Set SSID */
|
|
|
|
snprintf(eswifi->buf, sizeof(eswifi->buf), "C1=%s\r", eswifi->sta.ssid);
|
2018-12-21 16:00:56 +01:00
|
|
|
err = eswifi_at_cmd(eswifi, eswifi->buf);
|
|
|
|
if (err < 0) {
|
2018-10-09 17:49:44 +02:00
|
|
|
LOG_ERR("Unable to set SSID");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set passphrase */
|
|
|
|
snprintf(eswifi->buf, sizeof(eswifi->buf), "C2=%s\r", eswifi->sta.pass);
|
2018-12-21 16:00:56 +01:00
|
|
|
err = eswifi_at_cmd(eswifi, eswifi->buf);
|
|
|
|
if (err < 0) {
|
2018-10-09 17:49:44 +02:00
|
|
|
LOG_ERR("Unable to set passphrase");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set Security type */
|
|
|
|
snprintf(eswifi->buf, sizeof(eswifi->buf), "C3=%u\r",
|
|
|
|
eswifi->sta.security);
|
2018-12-21 16:00:56 +01:00
|
|
|
err = eswifi_at_cmd(eswifi, eswifi->buf);
|
|
|
|
if (err < 0) {
|
2018-10-09 17:49:44 +02:00
|
|
|
LOG_ERR("Unable to configure security");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Join Network */
|
2018-12-21 16:00:56 +01:00
|
|
|
err = eswifi_at_cmd_rsp(eswifi, connect, &rsp);
|
|
|
|
if (err < 0) {
|
2018-10-09 17:49:44 +02:00
|
|
|
LOG_ERR("Unable to join network");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Any IP assigned ? (dhcp offload or manually) */
|
2018-12-21 16:00:56 +01:00
|
|
|
err = __parse_ipv4_address(rsp, eswifi->sta.ssid,
|
2018-10-09 17:49:44 +02:00
|
|
|
(u8_t *)&addr.s4_addr);
|
2018-12-21 16:00:56 +01:00
|
|
|
if (err < 0) {
|
2018-10-09 17:49:44 +02:00
|
|
|
LOG_ERR("Unable to retrieve IP address");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG_DBG("ip = %d.%d.%d.%d", addr.s4_addr[0], addr.s4_addr[1],
|
|
|
|
addr.s4_addr[2], addr.s4_addr[3]);
|
|
|
|
|
|
|
|
net_if_ipv4_addr_add(eswifi->iface, &addr, NET_ADDR_DHCP, 0);
|
|
|
|
|
|
|
|
LOG_DBG("Connected!");
|
|
|
|
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eswifi_disconnect(struct eswifi_dev *eswifi)
|
|
|
|
{
|
|
|
|
char disconnect[] = "CD\r";
|
|
|
|
int err;
|
|
|
|
|
|
|
|
LOG_DBG("");
|
|
|
|
|
|
|
|
eswifi_lock(eswifi);
|
|
|
|
|
2018-12-21 16:00:56 +01:00
|
|
|
err = eswifi_at_cmd(eswifi, disconnect);
|
|
|
|
if (err < 0) {
|
2018-10-09 17:49:44 +02:00
|
|
|
LOG_ERR("Unable to disconnect network");
|
2018-12-21 16:00:56 +01:00
|
|
|
err = -EIO;
|
2018-10-09 17:49:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
|
2018-12-21 16:00:56 +01:00
|
|
|
return err;
|
2018-10-09 17:49:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void eswifi_request_work(struct k_work *item)
|
|
|
|
{
|
|
|
|
struct eswifi_dev *eswifi;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
LOG_DBG("");
|
|
|
|
|
|
|
|
eswifi = CONTAINER_OF(item, struct eswifi_dev, request_work);
|
|
|
|
|
|
|
|
switch (eswifi->req) {
|
|
|
|
case ESWIFI_REQ_CONNECT:
|
|
|
|
err = eswifi_connect(eswifi);
|
|
|
|
wifi_mgmt_raise_connect_result_event(eswifi->iface, err);
|
|
|
|
break;
|
|
|
|
case ESWIFI_REQ_DISCONNECT:
|
|
|
|
err = eswifi_disconnect(eswifi);
|
|
|
|
wifi_mgmt_raise_disconnect_result_event(eswifi->iface, err);
|
|
|
|
break;
|
|
|
|
case ESWIFI_REQ_SCAN:
|
|
|
|
eswifi_scan(eswifi);
|
|
|
|
break;
|
|
|
|
case ESWIFI_REQ_NONE:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eswifi_get_mac_addr(struct eswifi_dev *eswifi, u8_t addr[6])
|
|
|
|
{
|
|
|
|
char cmd[] = "Z5\r";
|
2018-12-21 16:00:56 +01:00
|
|
|
int ret, i, byte = 0;
|
|
|
|
char *rsp;
|
2018-10-09 17:49:44 +02:00
|
|
|
|
2018-12-21 16:00:56 +01:00
|
|
|
ret = eswifi_at_cmd_rsp(eswifi, cmd, &rsp);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
2018-10-09 17:49:44 +02:00
|
|
|
}
|
|
|
|
|
2018-12-21 16:00:56 +01:00
|
|
|
/* format is "ff:ff:ff:ff:ff:ff" */
|
|
|
|
for (i = 0; i < ret && byte < 6; i++) {
|
|
|
|
addr[byte++] = strtol(&rsp[i], NULL, 16);
|
|
|
|
i += 2;
|
2018-10-09 17:49:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (byte != 6) {
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eswifi_iface_init(struct net_if *iface)
|
|
|
|
{
|
|
|
|
struct eswifi_dev *eswifi = &eswifi0;
|
|
|
|
u8_t mac[6];
|
|
|
|
|
|
|
|
LOG_DBG("");
|
|
|
|
|
|
|
|
eswifi_lock(eswifi);
|
|
|
|
|
2018-12-21 16:00:56 +01:00
|
|
|
if (eswifi_reset(eswifi) < 0) {
|
2018-10-09 17:49:44 +02:00
|
|
|
LOG_ERR("Unable to reset device");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-12-21 16:00:56 +01:00
|
|
|
if (eswifi_get_mac_addr(eswifi, mac) < 0) {
|
2018-10-09 17:49:44 +02:00
|
|
|
LOG_ERR("Unable to read MAC address");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG_DBG("MAC Address %02X:%02X:%02X:%02X:%02X:%02X",
|
|
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
|
|
|
2019-01-10 13:22:22 +01:00
|
|
|
memcpy(eswifi->mac, mac, sizeof(eswifi->mac));
|
|
|
|
net_if_set_link_addr(iface, eswifi->mac, sizeof(eswifi->mac),
|
|
|
|
NET_LINK_ETHERNET);
|
2018-10-09 17:49:44 +02:00
|
|
|
|
|
|
|
eswifi->iface = iface;
|
|
|
|
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
|
|
|
|
eswifi_offload_init(eswifi);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eswifi_mgmt_scan(struct device *dev, scan_result_cb_t cb)
|
|
|
|
{
|
|
|
|
struct eswifi_dev *eswifi = dev->driver_data;
|
|
|
|
|
|
|
|
LOG_DBG("");
|
|
|
|
|
|
|
|
eswifi_lock(eswifi);
|
|
|
|
|
|
|
|
eswifi->scan_cb = cb;
|
|
|
|
eswifi->req = ESWIFI_REQ_SCAN;
|
|
|
|
k_work_submit_to_queue(&eswifi->work_q, &eswifi->request_work);
|
|
|
|
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eswifi_mgmt_disconnect(struct device *dev)
|
|
|
|
{
|
|
|
|
struct eswifi_dev *eswifi = dev->driver_data;
|
|
|
|
|
|
|
|
LOG_DBG("");
|
|
|
|
|
|
|
|
eswifi_lock(eswifi);
|
|
|
|
|
|
|
|
eswifi->req = ESWIFI_REQ_DISCONNECT;
|
|
|
|
k_work_submit_to_queue(&eswifi->work_q, &eswifi->request_work);
|
|
|
|
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-01-03 11:01:05 +01:00
|
|
|
static int __eswifi_sta_config(struct eswifi_dev *eswifi,
|
2018-10-09 17:49:44 +02:00
|
|
|
struct wifi_connect_req_params *params)
|
|
|
|
{
|
|
|
|
memcpy(eswifi->sta.ssid, params->ssid, params->ssid_length);
|
|
|
|
eswifi->sta.ssid[params->ssid_length] = '\0';
|
|
|
|
|
|
|
|
switch (params->security) {
|
|
|
|
case WIFI_SECURITY_TYPE_NONE:
|
|
|
|
eswifi->sta.pass[0] = '\0';
|
|
|
|
eswifi->sta.security = ESWIFI_SEC_OPEN;
|
|
|
|
break;
|
|
|
|
case WIFI_SECURITY_TYPE_PSK:
|
|
|
|
memcpy(eswifi->sta.pass, params->psk, params->psk_length);
|
|
|
|
eswifi->sta.pass[params->psk_length] = '\0';
|
|
|
|
eswifi->sta.security = ESWIFI_SEC_WPA2_MIXED;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2019-01-03 11:01:05 +01:00
|
|
|
if (params->channel == WIFI_CHANNEL_ANY) {
|
2019-03-26 19:57:45 -06:00
|
|
|
eswifi->sta.channel = 0U;
|
2019-01-03 11:01:05 +01:00
|
|
|
} else {
|
|
|
|
eswifi->sta.channel = params->channel;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eswifi_mgmt_connect(struct device *dev,
|
|
|
|
struct wifi_connect_req_params *params)
|
|
|
|
{
|
|
|
|
struct eswifi_dev *eswifi = dev->driver_data;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
LOG_DBG("");
|
|
|
|
|
|
|
|
eswifi_lock(eswifi);
|
|
|
|
|
|
|
|
err = __eswifi_sta_config(eswifi, params);
|
|
|
|
if (!err) {
|
|
|
|
eswifi->req = ESWIFI_REQ_CONNECT;
|
|
|
|
k_work_submit_to_queue(&eswifi->work_q,
|
|
|
|
&eswifi->request_work);
|
|
|
|
}
|
|
|
|
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(CONFIG_NET_IPV4)
|
|
|
|
static int eswifi_mgmt_ap_enable(struct device *dev,
|
|
|
|
struct wifi_connect_req_params *params)
|
|
|
|
{
|
|
|
|
struct eswifi_dev *eswifi = dev->driver_data;
|
|
|
|
struct net_if_ipv4 *ipv4 = eswifi->iface->config.ip.ipv4;
|
|
|
|
struct net_if_addr *unicast = NULL;
|
|
|
|
int err = -EIO, i;
|
|
|
|
|
|
|
|
LOG_DBG("");
|
|
|
|
|
|
|
|
eswifi_lock(eswifi);
|
|
|
|
|
|
|
|
if (eswifi->role == ESWIFI_ROLE_AP) {
|
|
|
|
err = -EALREADY;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = __eswifi_sta_config(eswifi, params);
|
|
|
|
if (err) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* security */
|
|
|
|
snprintf(eswifi->buf, sizeof(eswifi->buf), "A1=%u\r",
|
|
|
|
eswifi->sta.security);
|
|
|
|
err = eswifi_at_cmd(eswifi, eswifi->buf);
|
|
|
|
if (err < 0) {
|
|
|
|
LOG_ERR("Unable to set Security");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Passkey */
|
|
|
|
if (eswifi->sta.security != ESWIFI_SEC_OPEN) {
|
|
|
|
snprintf(eswifi->buf, sizeof(eswifi->buf), "A2=%s\r",
|
|
|
|
eswifi->sta.pass);
|
|
|
|
err = eswifi_at_cmd(eswifi, eswifi->buf);
|
|
|
|
if (err < 0) {
|
|
|
|
LOG_ERR("Unable to set passkey");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set SSID (0=no MAC, 1=append MAC) */
|
|
|
|
snprintf(eswifi->buf, sizeof(eswifi->buf), "AS=0,%s\r",
|
|
|
|
eswifi->sta.ssid);
|
|
|
|
err = eswifi_at_cmd(eswifi, eswifi->buf);
|
|
|
|
if (err < 0) {
|
|
|
|
LOG_ERR("Unable to set SSID");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set Channel */
|
|
|
|
snprintf(eswifi->buf, sizeof(eswifi->buf), "AC=%u\r",
|
|
|
|
eswifi->sta.channel);
|
|
|
|
err = eswifi_at_cmd(eswifi, eswifi->buf);
|
|
|
|
if (err < 0) {
|
|
|
|
LOG_ERR("Unable to set Channel");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set IP Address */
|
|
|
|
for (i = 0; ipv4 && i < NET_IF_MAX_IPV4_ADDR; i++) {
|
|
|
|
if (ipv4->unicast[i].is_used) {
|
|
|
|
unicast = &ipv4->unicast[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!unicast) {
|
|
|
|
LOG_ERR("No IPv4 assigned for AP mode");
|
|
|
|
err = -EADDRNOTAVAIL;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(eswifi->buf, sizeof(eswifi->buf), "Z6=%s\r",
|
|
|
|
net_sprint_ipv4_addr(&unicast->address.in_addr));
|
|
|
|
err = eswifi_at_cmd(eswifi, eswifi->buf);
|
|
|
|
if (err < 0) {
|
|
|
|
LOG_ERR("Unable to active access point");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Enable AP */
|
|
|
|
snprintf(eswifi->buf, sizeof(eswifi->buf), "AD\r");
|
|
|
|
err = eswifi_at_cmd(eswifi, eswifi->buf);
|
|
|
|
if (err < 0) {
|
|
|
|
LOG_ERR("Unable to active access point");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
eswifi->role = ESWIFI_ROLE_AP;
|
|
|
|
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
return 0;
|
|
|
|
error:
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static int eswifi_mgmt_ap_enable(struct device *dev,
|
|
|
|
struct wifi_connect_req_params *params)
|
|
|
|
{
|
|
|
|
LOG_ERR("IPv4 requested for AP mode");
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_NET_IPV4 */
|
|
|
|
|
|
|
|
static int eswifi_mgmt_ap_disable(struct device *dev)
|
|
|
|
{
|
|
|
|
struct eswifi_dev *eswifi = dev->driver_data;
|
|
|
|
char cmd[] = "AE\r";
|
|
|
|
int err;
|
|
|
|
|
|
|
|
eswifi_lock(eswifi);
|
|
|
|
|
|
|
|
err = eswifi_at_cmd(eswifi, cmd);
|
|
|
|
if (err < 0) {
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
eswifi->role = ESWIFI_ROLE_CLIENT;
|
2018-10-09 17:49:44 +02:00
|
|
|
|
|
|
|
eswifi_unlock(eswifi);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eswifi_init(struct device *dev)
|
|
|
|
{
|
|
|
|
struct eswifi_dev *eswifi = dev->driver_data;
|
|
|
|
|
|
|
|
LOG_DBG("");
|
|
|
|
|
|
|
|
eswifi->role = ESWIFI_ROLE_CLIENT;
|
|
|
|
k_mutex_init(&eswifi->mutex);
|
|
|
|
|
|
|
|
eswifi->bus = &eswifi_bus_ops_spi;
|
|
|
|
eswifi->bus->init(eswifi);
|
|
|
|
|
2018-11-21 12:16:05 -06:00
|
|
|
eswifi->resetn.dev = device_get_binding(
|
|
|
|
DT_INVENTEK_ESWIFI_ESWIFI0_RESETN_GPIOS_CONTROLLER);
|
2018-10-09 17:49:44 +02:00
|
|
|
if (!eswifi->resetn.dev) {
|
|
|
|
LOG_ERR("Failed to initialize GPIO driver: %s",
|
2018-11-21 12:16:05 -06:00
|
|
|
DT_INVENTEK_ESWIFI_ESWIFI0_RESETN_GPIOS_CONTROLLER);
|
2019-01-07 18:40:02 +01:00
|
|
|
return -ENODEV;
|
2018-10-09 17:49:44 +02:00
|
|
|
}
|
2018-11-21 12:16:05 -06:00
|
|
|
eswifi->resetn.pin = DT_INVENTEK_ESWIFI_ESWIFI0_RESETN_GPIOS_PIN;
|
2018-10-09 17:49:44 +02:00
|
|
|
gpio_pin_configure(eswifi->resetn.dev, eswifi->resetn.pin,
|
|
|
|
GPIO_DIR_OUT);
|
|
|
|
|
2018-11-21 12:16:05 -06:00
|
|
|
eswifi->wakeup.dev = device_get_binding(
|
|
|
|
DT_INVENTEK_ESWIFI_ESWIFI0_WAKEUP_GPIOS_CONTROLLER);
|
2018-10-09 17:49:44 +02:00
|
|
|
if (!eswifi->wakeup.dev) {
|
|
|
|
LOG_ERR("Failed to initialize GPIO driver: %s",
|
2018-11-21 12:16:05 -06:00
|
|
|
DT_INVENTEK_ESWIFI_ESWIFI0_WAKEUP_GPIOS_CONTROLLER);
|
2019-01-07 18:40:02 +01:00
|
|
|
return -ENODEV;
|
2018-10-09 17:49:44 +02:00
|
|
|
}
|
2018-11-21 12:16:05 -06:00
|
|
|
eswifi->wakeup.pin = DT_INVENTEK_ESWIFI_ESWIFI0_WAKEUP_GPIOS_PIN;
|
2018-10-09 17:49:44 +02:00
|
|
|
gpio_pin_configure(eswifi->wakeup.dev, eswifi->wakeup.pin,
|
|
|
|
GPIO_DIR_OUT);
|
|
|
|
gpio_pin_write(eswifi->wakeup.dev, eswifi->wakeup.pin, 1);
|
|
|
|
|
|
|
|
k_work_q_start(&eswifi->work_q, eswifi_work_q_stack,
|
|
|
|
K_THREAD_STACK_SIZEOF(eswifi_work_q_stack),
|
|
|
|
CONFIG_SYSTEM_WORKQUEUE_PRIORITY - 1);
|
|
|
|
|
|
|
|
k_work_init(&eswifi->request_work, eswifi_request_work);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct net_wifi_mgmt_offload eswifi_offload_api = {
|
|
|
|
.iface_api.init = eswifi_iface_init,
|
|
|
|
.scan = eswifi_mgmt_scan,
|
|
|
|
.connect = eswifi_mgmt_connect,
|
|
|
|
.disconnect = eswifi_mgmt_disconnect,
|
2019-01-03 11:01:05 +01:00
|
|
|
.ap_enable = eswifi_mgmt_ap_enable,
|
|
|
|
.ap_disable = eswifi_mgmt_ap_disable,
|
2018-10-09 17:49:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
NET_DEVICE_OFFLOAD_INIT(eswifi_mgmt, CONFIG_WIFI_ESWIFI_NAME,
|
|
|
|
eswifi_init, &eswifi0, NULL,
|
|
|
|
CONFIG_WIFI_INIT_PRIORITY, &eswifi_offload_api, 1500);
|