365 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			365 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*
 | 
						|
 * 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
 |