Files
TAIXIN/sdk/lib/net/wifi/wifi_dev.c

203 lines
5.8 KiB
C
Raw Normal View History

#include "sys_config.h"
#include "typesdef.h"
#include "list.h"
#include "dev.h"
#include "devid.h"
#include "osal/string.h"
#include "osal/mutex.h"
#include "osal/work.h"
#include "osal/semaphore.h"
#include "osal/timer.h"
#include "hal/netdev.h"
#include "hal/dma.h"
#include "hal/netdev.h"
#include "lib/common/common.h"
#include "lib/heap/sysheap.h"
#include "lib/umac/ieee80211.h"
#include "lib/skb/skb.h"
#include "lib/skb/skb_list.h"
#include "lib/net/utils.h"
#include "syscfg.h"
#define WIFI_DEV_ICMP_MONITOR 0
struct wifi_dev {
struct netdev wifi;
netdev_input_cb input_cb;
void *input_priv;
uint8 addr[6];
uint8 ifidx;
uint8 icmp_mntr: 1, rev: 7;
uint32 no_mem;
};
static void wifi_dev_icmp_monitor(struct wifi_dev *wifi, uint8 *data, uint32 len, const char *prefix)
{
#if WIFI_DEV_ICMP_MONITOR
if (wifi->icmp_mntr) {
icmp_pkt_monitor(prefix, data, len);
}
#endif
}
static void wifi_dev_icmp_monitor_scatter(struct wifi_dev *wifi, scatter_data *data, uint32 count, const char *prefix)
{
#if WIFI_DEV_ICMP_MONITOR
if (wifi->icmp_mntr) {
icmp_pkt_monitor_scatter(prefix, data, count);
}
#endif
}
static int32 wifi_dev_open(struct netdev *ndev, netdev_input_cb cb, netdev_event_cb evt_cb, void *priv)
{
struct wifi_dev *wifi = (struct wifi_dev *)ndev;
uint8 ifidx = (wifi->ifidx == WIFI_MODE_APSTA ? WIFI_MODE_STA : wifi->ifidx);
if (cb) {
uint32 flags = disable_irq();
wifi->input_cb = cb;
wifi->input_priv = priv;
enable_irq(flags);
}
return ieee80211_iface_start(ifidx);
}
static int32 wifi_dev_close(struct netdev *ndev)
{
struct wifi_dev *wifi = (struct wifi_dev *)ndev;
uint8 ifidx = (wifi->ifidx == WIFI_MODE_APSTA ? WIFI_MODE_STA : wifi->ifidx);
return ieee80211_iface_stop(ifidx);
}
static int32 wifi_dev_send(struct netdev *ndev, uint8 *data, uint32 size)
{
struct wifi_dev *wifi = (struct wifi_dev *)ndev;
uint8 ifidx = (wifi->ifidx == WIFI_MODE_APSTA ? 0 : wifi->ifidx);
wifi->wifi.tx_bytes += size;
wifi_dev_icmp_monitor(wifi, data, size, "WIFI_DEV TX");
return ieee80211_tx(ifidx, (uint8 *)data, size);
}
static int32 wifi_dev_scatter_send(struct netdev *ndev, scatter_data *data, uint32 count)
{
struct wifi_dev *wifi = (struct wifi_dev *)ndev;
uint8 ifidx = (wifi->ifidx == WIFI_MODE_APSTA ? 0 : wifi->ifidx);
wifi->wifi.tx_bytes += scatter_size(data, count);
wifi_dev_icmp_monitor_scatter(wifi, data, count, "WIFI_DEV TX");
return ieee80211_scatter_tx(ifidx, data, count);
}
static int32 wifi_dev_hook_data(struct netdev *ndev, uint8 *data, uint32 len)
{
struct wifi_dev *wifi = (struct wifi_dev *)ndev;
uint8 ifidx = wifi->ifidx == WIFI_MODE_APSTA ? WIFI_MODE_STA : wifi->ifidx;
if (IS_MCAST_ADDR(data) && (ieee80211_conf_get_connstate(ifidx) >= WPA_GROUP_HANDSHAKE)) {
return IEEE80211_PKTHDL_CONTINUE;
}
return ieee80211_hook_ext_data(ifidx, 1, data, len);
}
static int32 wifi_dev_ioctl(struct netdev *ndev, uint32 cmd, uint32 param1, uint32 param2)
{
int32 ret = RET_OK;
struct wifi_dev *wifi = (struct wifi_dev *)ndev;
uint8 ifidx = (wifi->ifidx == WIFI_MODE_APSTA ? WIFI_MODE_STA : wifi->ifidx);
switch (cmd) {
case NETDEV_IOCTL_GET_ADDR:
ieee80211_conf_get_mac(ifidx, wifi->addr);
os_memcpy((uint8 *)param1, wifi->addr, 6);
break;
case NETDEV_IOCTL_SET_ADDR:
ieee80211_conf_set_mac(ifidx, (uint8 *)param1);
os_memcpy(wifi->addr, (uint8 *)param1, 6);
break;
case NETDEV_IOCTL_GET_LINK_STATUS:
ret = (ieee80211_conf_get_connstate(ifidx) >= WPA_GROUP_HANDSHAKE);
break;
case NETDEV_IOCTL_GET_LINK_SPEED:
break;
#if WIFI_SINGLE_DEV
case NETDEV_IOCTL_SET_WIFI_MODE:
wifi->ifidx = (uint8)param1;
break;
#endif
case NETDEV_IOCTL_HOOK_INPUTDATA:
ret = !wifi_dev_hook_data(ndev, (uint8 *)param1, param2);
break;
case NETDEV_IOCTL_ENABLE_ICMPMNTR:
wifi->icmp_mntr = param1 ? 1 : 0;
break;
default:
ret = -ENOTSUPP;
break;
}
return ret;
}
int32 sys_wifi_recv(void *priv, uint8 *data, uint32 len, uint32 flags)
{
netdev_input_cb input_cb;
void *input_priv;
struct wifi_dev *wifi = (struct wifi_dev *)priv;
uint32 f = disable_irq();
input_cb = wifi->input_cb;
input_priv = wifi->input_priv;
enable_irq(f);
if (input_cb) {
wifi_dev_icmp_monitor(wifi, data, len, "WIFI_DEV RX");
input_cb(&wifi->wifi, data, len, input_priv);
wifi->wifi.rx_bytes += len;
}
return RET_OK;
}
static const struct netdev_hal_ops wifi_dev_ops = {
.open = wifi_dev_open,
.close = wifi_dev_close,
.ioctl = wifi_dev_ioctl,
.send_data = wifi_dev_send,
.send_scatter_data = wifi_dev_scatter_send,
};
__init void *sys_wifi_register(uint32 ifidx)
{
struct wifi_dev *wifi;
uint32 dev_id = HG_WIFI0_DEVID + ifidx - 1;
#if WIFI_SINGLE_DEV
dev_id = HG_WIFI0_DEVID;
wifi = (struct wifi_dev *)dev_get(dev_id);
if (wifi) {
return wifi;
}
#endif
wifi = (struct wifi_dev *)os_zalloc(sizeof(struct wifi_dev));
ASSERT(wifi);
wifi->wifi.dev.ops = (const struct devobj_ops *)&wifi_dev_ops;
wifi->ifidx = (uint8)ifidx;
dev_register(dev_id, (struct dev_obj *)wifi);
return wifi;
}
void wifi_dev_status(uint32 dev_id)
{
struct wifi_dev *wifi = (struct wifi_dev *)dev_get(dev_id);
if (wifi == NULL) {
return;
}
os_printf("WiFi Dev Status: no_mem=%u\r\n", wifi->no_mem);
os_printf(" wifi: tx_bytes:%llu, rx_bytes:%llu\r\n", wifi->wifi.tx_bytes, wifi->wifi.rx_bytes);
}