365 lines
8.9 KiB
C
365 lines
8.9 KiB
C
/*
|
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Change Logs:
|
|
* Date Author Notes
|
|
* 2018-08-14 tyx the first version
|
|
*/
|
|
|
|
#include <rthw.h>
|
|
#include <rtthread.h>
|
|
#include <wlan_dev.h>
|
|
#include <wlan_prot.h>
|
|
|
|
#define DBG_TAG "WLAN.prot"
|
|
#ifdef RT_WLAN_PROT_DEBUG
|
|
#define DBG_LVL DBG_LOG
|
|
#else
|
|
#define DBG_LVL DBG_INFO
|
|
#endif /* RT_WLAN_PROT_DEBUG */
|
|
#include <rtdbg.h>
|
|
|
|
#ifdef RT_WLAN_PROT_ENABLE
|
|
|
|
#if RT_WLAN_PROT_NAME_LEN < 4
|
|
#error "The name is too short"
|
|
#endif
|
|
|
|
struct rt_wlan_prot_event_des
|
|
{
|
|
rt_wlan_prot_event_handler handler;
|
|
struct rt_wlan_prot *prot;
|
|
};
|
|
|
|
static struct rt_wlan_prot *_prot[RT_WLAN_PROT_MAX];
|
|
|
|
static struct rt_wlan_prot_event_des prot_event_tab[RT_WLAN_PROT_EVT_MAX][RT_WLAN_PROT_MAX];
|
|
|
|
static void rt_wlan_prot_event_handle(struct rt_wlan_device *wlan, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff, void *parameter)
|
|
{
|
|
int i;
|
|
struct rt_wlan_prot *wlan_prot;
|
|
struct rt_wlan_prot *prot;
|
|
rt_wlan_prot_event_handler handler;
|
|
rt_wlan_prot_event_t prot_event;
|
|
|
|
LOG_D("F:%s L:%d event:%d", __FUNCTION__, __LINE__, event);
|
|
|
|
wlan_prot = wlan->prot;
|
|
handler = RT_NULL;
|
|
prot = RT_NULL;
|
|
switch (event)
|
|
{
|
|
case RT_WLAN_DEV_EVT_INIT_DONE:
|
|
{
|
|
LOG_D("L%d event: INIT_DONE", __LINE__);
|
|
prot_event = RT_WLAN_PROT_EVT_INIT_DONE;
|
|
break;
|
|
}
|
|
case RT_WLAN_DEV_EVT_CONNECT:
|
|
{
|
|
LOG_D("L%d event: CONNECT", __LINE__);
|
|
prot_event = RT_WLAN_PROT_EVT_CONNECT;
|
|
break;
|
|
}
|
|
case RT_WLAN_DEV_EVT_DISCONNECT:
|
|
{
|
|
LOG_D("L%d event: DISCONNECT", __LINE__);
|
|
prot_event = RT_WLAN_PROT_EVT_DISCONNECT;
|
|
break;
|
|
}
|
|
case RT_WLAN_DEV_EVT_AP_START:
|
|
{
|
|
LOG_D("L%d event: AP_START", __LINE__);
|
|
prot_event = RT_WLAN_PROT_EVT_AP_START;
|
|
break;
|
|
}
|
|
case RT_WLAN_DEV_EVT_AP_STOP:
|
|
{
|
|
LOG_D("L%d event: AP_STOP", __LINE__);
|
|
prot_event = RT_WLAN_PROT_EVT_AP_STOP;
|
|
break;
|
|
}
|
|
case RT_WLAN_DEV_EVT_AP_ASSOCIATED:
|
|
{
|
|
LOG_D("L%d event: AP_ASSOCIATED", __LINE__);
|
|
prot_event = RT_WLAN_PROT_EVT_AP_ASSOCIATED;
|
|
break;
|
|
}
|
|
case RT_WLAN_DEV_EVT_AP_DISASSOCIATED:
|
|
{
|
|
LOG_D("L%d event: AP_DISASSOCIATED", __LINE__);
|
|
prot_event = RT_WLAN_PROT_EVT_AP_DISASSOCIATED;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
for (i = 0; i < RT_WLAN_PROT_MAX; i++)
|
|
{
|
|
if ((prot_event_tab[prot_event][i].handler != RT_NULL) &&
|
|
(prot_event_tab[prot_event][i].prot->id == wlan_prot->id))
|
|
{
|
|
handler = prot_event_tab[prot_event][i].handler;
|
|
prot = prot_event_tab[prot_event][i].prot;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (handler != RT_NULL)
|
|
{
|
|
handler(prot, wlan, prot_event);
|
|
}
|
|
}
|
|
|
|
static struct rt_wlan_device *rt_wlan_prot_find_by_name(const char *name)
|
|
{
|
|
rt_device_t device;
|
|
|
|
if (name == RT_NULL)
|
|
{
|
|
LOG_E("F:%s L:%d Parameter Wrongful", __FUNCTION__, __LINE__);
|
|
return RT_NULL;
|
|
}
|
|
device = rt_device_find(name);
|
|
if (device == RT_NULL)
|
|
{
|
|
LOG_E("F:%s L:%d not find wlan dev!! name:%s", __FUNCTION__, __LINE__, name);
|
|
return RT_NULL;
|
|
}
|
|
return (struct rt_wlan_device *)device;
|
|
}
|
|
|
|
rt_err_t rt_wlan_prot_attach(const char *dev_name, const char *prot_name)
|
|
{
|
|
struct rt_wlan_device *wlan;
|
|
|
|
wlan = rt_wlan_prot_find_by_name(dev_name);
|
|
if (wlan == RT_NULL)
|
|
{
|
|
return -RT_ERROR;
|
|
}
|
|
return rt_wlan_prot_attach_dev(wlan, prot_name);
|
|
}
|
|
|
|
rt_err_t rt_wlan_prot_detach(const char *name)
|
|
{
|
|
struct rt_wlan_device *wlan;
|
|
|
|
wlan = rt_wlan_prot_find_by_name(name);
|
|
if (wlan == RT_NULL)
|
|
{
|
|
return -RT_ERROR;
|
|
}
|
|
return rt_wlan_prot_detach_dev(wlan);
|
|
}
|
|
|
|
rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_name)
|
|
{
|
|
int i = 0;
|
|
struct rt_wlan_prot *prot = wlan->prot;
|
|
rt_wlan_dev_event_handler handler = rt_wlan_prot_event_handle;
|
|
|
|
if (wlan == RT_NULL)
|
|
{
|
|
LOG_E("F:%s L:%d wlan is null", __FUNCTION__, __LINE__);
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
if (prot != RT_NULL &&
|
|
(rt_strcmp(prot->name, prot_name) == 0))
|
|
{
|
|
LOG_D("prot is register");
|
|
return RT_EOK;
|
|
}
|
|
|
|
/* if prot not NULL */
|
|
if (prot != RT_NULL)
|
|
rt_wlan_prot_detach_dev(wlan);
|
|
|
|
#ifdef RT_WLAN_PROT_LWIP_PBUF_FORCE
|
|
if (rt_strcmp(RT_WLAN_PROT_LWIP_NAME, prot_name) != 0)
|
|
{
|
|
return -RT_ERROR;
|
|
}
|
|
#endif
|
|
/* find prot */
|
|
for (i = 0; i < RT_WLAN_PROT_MAX; i++)
|
|
{
|
|
if ((_prot[i] != RT_NULL) && (rt_strcmp(_prot[i]->name, prot_name) == 0))
|
|
{
|
|
/* attach prot */
|
|
wlan->prot = _prot[i]->ops->dev_reg_callback(_prot[i], wlan);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= RT_WLAN_PROT_MAX)
|
|
{
|
|
LOG_E("F:%s L:%d not find wlan protocol", __FUNCTION__, __LINE__);
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_CONNECT, handler, RT_NULL);
|
|
rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_DISCONNECT, handler, RT_NULL);
|
|
rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_START, handler, RT_NULL);
|
|
rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_STOP, handler, RT_NULL);
|
|
rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_ASSOCIATED, handler, RT_NULL);
|
|
rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_DISASSOCIATED, handler, RT_NULL);
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
rt_err_t rt_wlan_prot_detach_dev(struct rt_wlan_device *wlan)
|
|
{
|
|
struct rt_wlan_prot *prot = wlan->prot;
|
|
rt_wlan_dev_event_t event;
|
|
|
|
if (prot == RT_NULL)
|
|
return RT_EOK;
|
|
|
|
for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event ++)
|
|
{
|
|
rt_wlan_dev_unregister_event_handler(wlan, event, rt_wlan_prot_event_handle);
|
|
}
|
|
|
|
/* detach prot */
|
|
prot->ops->dev_unreg_callback(prot, wlan);
|
|
wlan->prot = RT_NULL;
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
rt_err_t rt_wlan_prot_regisetr(struct rt_wlan_prot *prot)
|
|
{
|
|
int i;
|
|
rt_uint32_t id;
|
|
static rt_uint8_t num;
|
|
|
|
/* Parameter checking */
|
|
if ((prot == RT_NULL) ||
|
|
(prot->ops->prot_recv == RT_NULL) ||
|
|
(prot->ops->dev_reg_callback == RT_NULL))
|
|
{
|
|
LOG_E("F:%s L:%d Parameter Wrongful", __FUNCTION__, __LINE__);
|
|
return -RT_EINVAL;
|
|
}
|
|
|
|
/* save prot */
|
|
for (i = 0; i < RT_WLAN_PROT_MAX; i++)
|
|
{
|
|
if (_prot[i] == RT_NULL)
|
|
{
|
|
id = (RT_LWAN_ID_PREFIX << 16) | num;
|
|
prot->id = id;
|
|
_prot[i] = prot;
|
|
num ++;
|
|
break;
|
|
}
|
|
else if (rt_strcmp(_prot[i]->name, prot->name) == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* is full */
|
|
if (i >= RT_WLAN_PROT_MAX)
|
|
{
|
|
LOG_E("F:%s L:%d Space full", __FUNCTION__, __LINE__);
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
rt_err_t rt_wlan_prot_event_register(struct rt_wlan_prot *prot, rt_wlan_prot_event_t event, rt_wlan_prot_event_handler handler)
|
|
{
|
|
int i;
|
|
|
|
if ((prot == RT_NULL) || (handler == RT_NULL))
|
|
{
|
|
return -RT_EINVAL;
|
|
}
|
|
|
|
for (i = 0; i < RT_WLAN_PROT_MAX; i++)
|
|
{
|
|
if (prot_event_tab[event][i].handler == RT_NULL)
|
|
{
|
|
prot_event_tab[event][i].handler = handler;
|
|
prot_event_tab[event][i].prot = prot;
|
|
return RT_EOK;
|
|
}
|
|
}
|
|
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
rt_err_t rt_wlan_prot_event_unregister(struct rt_wlan_prot *prot, rt_wlan_prot_event_t event)
|
|
{
|
|
int i;
|
|
|
|
if (prot == RT_NULL)
|
|
{
|
|
return -RT_EINVAL;
|
|
}
|
|
|
|
for (i = 0; i < RT_WLAN_PROT_MAX; i++)
|
|
{
|
|
if ((prot_event_tab[event][i].handler != RT_NULL) &&
|
|
(prot_event_tab[event][i].prot == prot))
|
|
{
|
|
rt_memset(&prot_event_tab[event][i], 0, sizeof(struct rt_wlan_prot_event_des));
|
|
return RT_EOK;
|
|
}
|
|
}
|
|
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
rt_err_t rt_wlan_prot_transfer_dev(struct rt_wlan_device *wlan, void *buff, int len)
|
|
{
|
|
if (wlan->ops->wlan_send != RT_NULL)
|
|
{
|
|
return wlan->ops->wlan_send(wlan, buff, len);
|
|
}
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
rt_err_t rt_wlan_dev_transfer_prot(struct rt_wlan_device *wlan, void *buff, int len)
|
|
{
|
|
struct rt_wlan_prot *prot = wlan->prot;
|
|
|
|
if (prot != RT_NULL)
|
|
{
|
|
return prot->ops->prot_recv(wlan, buff, len);
|
|
}
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
extern int rt_wlan_prot_ready_event(struct rt_wlan_device *wlan, struct rt_wlan_buff *buff);
|
|
int rt_wlan_prot_ready(struct rt_wlan_device *wlan, struct rt_wlan_buff *buff)
|
|
{
|
|
return rt_wlan_prot_ready_event(wlan, buff);
|
|
}
|
|
|
|
void rt_wlan_prot_dump(void)
|
|
{
|
|
int i;
|
|
|
|
rt_kprintf(" name id \n");
|
|
rt_kprintf("-------- --------\n");
|
|
for (i = 0; i < RT_WLAN_PROT_MAX; i++)
|
|
{
|
|
if (_prot[i] != RT_NULL)
|
|
{
|
|
rt_kprintf("%-8.8s ", _prot[i]->name);
|
|
rt_kprintf("%08x\n", _prot[i]->id);
|
|
}
|
|
}
|
|
}
|
|
#endif
|