/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-08-14 tyx the first version */ #include #include #include #include #define DBG_ENABLE #ifdef RT_WLAN_PROT_DEBUG #define DBG_LEVEL DBG_LOG #else #define DBG_LEVEL DBG_INFO #endif #define DBG_SECTION_NAME "WLAN.prot" #define DBG_COLOR #include #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_t event; 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, 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; } for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event ++) { if (rt_wlan_dev_register_event_handler(wlan, event, rt_wlan_prot_event_handle, RT_NULL) != RT_EOK) { LOG_E("prot register event filed:%d", event); } } 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); } } }