mirror of
https://gitee.com/Vancouver2017/luban-lite.git
synced 2025-12-24 21:18:54 +00:00
319 lines
8.6 KiB
C
319 lines
8.6 KiB
C
#include "atbm_hal.h"
|
|
|
|
#if CONFIG_WIFI_BT_COMB
|
|
#define IEEE80211_BLE_SKB_HEADNEED 128
|
|
static void ieee80211_ble_dump(const char *string,atbm_uint8 *mem,atbm_size_t len)
|
|
{
|
|
#if 0
|
|
atbm_size_t i = 0;
|
|
atbm_printk_err("[%s]:\n",string);
|
|
|
|
for(i = 0; i< len ; i++){
|
|
if(!(i % 16)){
|
|
atbm_printk_err("\n");
|
|
}
|
|
atbm_printk_err("[%x]",mem[i]);
|
|
}
|
|
#endif
|
|
}
|
|
static int ieee80211_ble_thread_wakeup(struct ieee80211_ble_thread *thread)
|
|
{
|
|
atbm_os_wakeup_event(&thread->wq);
|
|
return 0;
|
|
}
|
|
|
|
static int ieee80211_ble_thread_deinit(struct ieee80211_ble_thread *thread)
|
|
{
|
|
void *bh;
|
|
struct atbmwifi_common *hw_priv = thread->hw_priv;
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
|
|
atbm_spin_lock_bh(&ble_local->ble_spin_lock);
|
|
bh = thread->thread;
|
|
thread->thread = ATBM_NULL;
|
|
atbm_spin_unlock_bh(&ble_local->ble_spin_lock);
|
|
if (bh){
|
|
atbm_stopThreadInternal(bh);
|
|
}
|
|
atbm_os_delete_waitevent(&thread->wq);
|
|
return 0;
|
|
}
|
|
|
|
static int ieee80211_ble_thread_init(struct ieee80211_ble_thread *thread)
|
|
{
|
|
atbm_os_init_waitevent(&thread->wq);
|
|
|
|
thread->thread = atbm_createThreadInternal(thread->name,thread->thread_fn, thread, thread->prio);
|
|
|
|
if (!thread->thread){
|
|
wifi_printk(WIFI_DBG_ERROR, "sdio %s err\n",thread->name);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
static int ieee80211_ble_xmit_thread(struct ieee80211_ble_thread *thread)
|
|
{
|
|
struct atbm_buff *skb;
|
|
struct atbmwifi_common *hw_priv= thread->hw_priv;
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
|
|
while(1){
|
|
atbm_os_wait_event_timeout(&thread->wq, 10*HZ);
|
|
while((skb = atbm_skb_dequeue(&ble_local->ble_xmit_queue))){
|
|
|
|
/*
|
|
*start tx
|
|
*/
|
|
//printk("[ble xmit]:len [%d]\n",skb->len);
|
|
ieee80211_ble_dump(__FUNCTION__,skb->abuf,skb->dlen);
|
|
atbm_ble_do_ble_xmit(hw_priv,skb->abuf,skb->dlen);
|
|
/*
|
|
*free skb
|
|
*/
|
|
atbm_dev_kfree_skb(skb);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
static int ieee80211_ble_xmit_init(struct atbmwifi_common *hw_priv)
|
|
{
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
struct ieee80211_ble_thread *thread = &ble_local->xmit_thread;
|
|
|
|
atbm_skb_queue_head_init(&ble_local->ble_xmit_queue);
|
|
|
|
thread->flags = 0;
|
|
thread->name = "ble_xmit";
|
|
thread->period_handle = NULL;
|
|
thread->thread_fn = ieee80211_ble_xmit_thread;
|
|
thread->hw_priv = hw_priv;
|
|
thread->prio = BLE_XMIT_PRIO;
|
|
|
|
if(ieee80211_ble_thread_init(thread)){
|
|
wifi_printk(WIFI_DBG_ERROR, "ble_xmit thread err\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
void ieee80211_ble_recv(struct atbmwifi_common *hw_priv, struct atbm_buff *skb)
|
|
{
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
|
|
atbm_spin_lock_bh(&ble_local->ble_spin_lock);
|
|
|
|
if(ble_local->ble_started == ATBM_TRUE){
|
|
atbm_skb_queue_tail(&ble_local->ble_recv_queue,skb);
|
|
ieee80211_ble_thread_wakeup(&ble_local->recv_thread);
|
|
}else {
|
|
atbm_dev_kfree_skb(skb);
|
|
}
|
|
|
|
atbm_spin_unlock_bh(&ble_local->ble_spin_lock);
|
|
}
|
|
static int ieee80211_ble_recv_thread(struct ieee80211_ble_thread *thread)
|
|
{
|
|
struct atbm_buff *skb;
|
|
struct atbmwifi_common *hw_priv = thread->hw_priv;
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
int (*ble_cb)(struct atbmwifi_common *hw_priv, atbm_uint8 * buff, atbm_size_t buff_size, enum ieee80211_ble_msg_type msg_type);
|
|
|
|
while(1){
|
|
atbm_os_wait_event_timeout(&thread->wq, 10*HZ);
|
|
atbm_os_mutexLock(&ble_local->ble_mutex_lock, 0);
|
|
ble_cb = ble_local->ble_recv_callback;
|
|
|
|
while((skb = atbm_skb_dequeue(&ble_local->ble_recv_queue))){
|
|
struct ieee80211_ble_status *status = (struct ieee80211_ble_status *)&skb->cb[0];
|
|
wifi_printk(WIFI_DBG_MSG, "%s:ble(%d)(%d)\n",__FUNCTION__,skb->dlen,status->msg_type);
|
|
if(ble_cb) ble_cb(hw_priv,skb->abuf,skb->dlen,status->msg_type);
|
|
|
|
atbm_dev_kfree_skb(skb);
|
|
}
|
|
|
|
atbm_os_mutexUnLock(&ble_local->ble_mutex_lock);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
static int ieee80211_ble_recv_init(struct atbmwifi_common *hw_priv)
|
|
{
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
struct ieee80211_ble_thread *thread = &ble_local->recv_thread;
|
|
|
|
atbm_skb_queue_head_init(&ble_local->ble_recv_queue);
|
|
|
|
thread->flags = 0;
|
|
thread->name = "ble_recv";
|
|
thread->period_handle = NULL;
|
|
thread->thread_fn = ieee80211_ble_recv_thread;
|
|
thread->hw_priv = hw_priv;
|
|
thread->prio = BLE_RECV_PRIO;
|
|
|
|
if(ieee80211_ble_thread_init(thread)){
|
|
wifi_printk(WIFI_DBG_ERROR, "ble_recv thread err\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
static int ieee80211_ble_xmit_exit(struct atbmwifi_common *hw_priv)
|
|
{
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
struct ieee80211_ble_thread *thread = &ble_local->xmit_thread;
|
|
|
|
ieee80211_ble_thread_deinit(thread);
|
|
|
|
atbm_skb_queue_purge(&ble_local->ble_xmit_queue);
|
|
return 0;
|
|
}
|
|
|
|
static int ieee80211_ble_recv_exit(struct atbmwifi_common *hw_priv)
|
|
{
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
struct ieee80211_ble_thread *thread = &ble_local->recv_thread;
|
|
|
|
ieee80211_ble_thread_deinit(thread);
|
|
|
|
atbm_skb_queue_purge(&ble_local->ble_recv_queue);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int ieee80211_ble_commb_start(struct atbmwifi_common *hw_priv)
|
|
{
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
|
|
wifi_printk(WIFI_DBG_INIT, "ble start\n");
|
|
if(ieee80211_ble_recv_init(hw_priv)){
|
|
goto fail_recv;
|
|
}
|
|
|
|
if(ieee80211_ble_xmit_init(hw_priv)){
|
|
goto fail_xmit;
|
|
}
|
|
/*
|
|
*start sucess
|
|
*/
|
|
|
|
atbm_spin_lock_bh(&ble_local->ble_spin_lock);
|
|
ble_local->ble_started = ATBM_TRUE;
|
|
atbm_spin_unlock_bh(&ble_local->ble_spin_lock);
|
|
return 0;
|
|
fail_xmit:
|
|
ieee80211_ble_recv_exit(hw_priv);
|
|
fail_recv:
|
|
wifi_printk(WIFI_DBG_INIT,"ble start err\n");
|
|
return -1;
|
|
|
|
}
|
|
|
|
int ieee80211_ble_commb_stop(struct atbmwifi_common *hw_priv)
|
|
{
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
|
|
ble_local->ble_started = ATBM_FALSE;
|
|
|
|
ieee80211_ble_xmit_exit(hw_priv);
|
|
ieee80211_ble_recv_exit(hw_priv);
|
|
wifi_printk(WIFI_DBG_INIT, "ble stop\n");
|
|
return 0;
|
|
}
|
|
|
|
int ieee80211_ble_commb_xmit(struct atbmwifi_common* hw_priv, atbm_uint8* xmit, atbm_size_t xmit_len)
|
|
{
|
|
//struct ieee80211_local *local = ble_to_local(pble_dev);
|
|
struct ieee80211_ble_buff *ble_buff;
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
|
|
struct atbm_buff *skb;
|
|
ieee80211_ble_dump(__FUNCTION__,xmit,xmit_len);
|
|
ble_buff = atbm_container_of((void *)xmit, struct ieee80211_ble_buff, mem);
|
|
|
|
skb = ble_buff->skb;
|
|
|
|
ATBM_BUG_ON((skb->abuf + IEEE80211_BLE_SKB_HEADNEED) != (atbm_uint8*)ble_buff);
|
|
|
|
atbm_skb_reserve(skb, IEEE80211_BLE_SKB_HEADNEED+sizeof(struct ieee80211_ble_buff));
|
|
atbm_skb_put(skb,xmit_len);
|
|
|
|
atbm_spin_lock_bh(&ble_local->ble_spin_lock);
|
|
|
|
if(ble_local->ble_started == ATBM_TRUE){
|
|
//printk("[%s]:len [%d]\n",__func__,skb->len);
|
|
atbm_skb_queue_tail(&ble_local->ble_xmit_queue,skb);
|
|
ieee80211_ble_thread_wakeup(&ble_local->xmit_thread);
|
|
}else {
|
|
atbm_dev_kfree_skb(skb);
|
|
}
|
|
|
|
atbm_spin_unlock_bh(&ble_local->ble_spin_lock);
|
|
return 0;
|
|
}
|
|
|
|
int ieee80211_ble_commb_subscribe(struct atbmwifi_common* hw_priv,
|
|
int (*recv)(struct atbmwifi_common* hw_priv, atbm_uint8* recv, atbm_size_t recv_len, enum ieee80211_ble_msg_type msg_type))
|
|
{
|
|
//struct ieee80211_local *local = ble_to_local(pble_dev);
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
|
|
wifi_printk(WIFI_DBG_INIT,"ble subscribe\n");
|
|
atbm_os_mutexLock(&ble_local->ble_mutex_lock, 0);
|
|
ble_local->ble_recv_callback = recv;
|
|
atbm_os_mutexUnLock(&ble_local->ble_mutex_lock);
|
|
|
|
return 0;
|
|
}
|
|
int ieee80211_ble_commb_unsubscribe(struct atbmwifi_common* hw_priv)
|
|
{
|
|
//struct ieee80211_local *local = ble_to_local(pble_dev);
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
wifi_printk(WIFI_DBG_INIT,"ble unsubscribe\n");
|
|
atbm_os_mutexLock(&ble_local->ble_mutex_lock, 0);
|
|
ble_local->ble_recv_callback = NULL;
|
|
atbm_os_mutexUnLock(&ble_local->ble_mutex_lock);
|
|
|
|
synchronize_rcu();
|
|
return 0;
|
|
}
|
|
char *ieee80211_ble_commb_ble_alloc_xmit(atbm_size_t len)
|
|
{
|
|
struct atbm_buff *skb;
|
|
struct ieee80211_ble_buff *ble_buff;
|
|
|
|
skb = atbm_dev_alloc_skb(len + IEEE80211_BLE_SKB_HEADNEED + sizeof(struct ieee80211_ble_buff));
|
|
|
|
if(skb == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
ble_buff = (struct ieee80211_ble_buff *)(skb->abuf + IEEE80211_BLE_SKB_HEADNEED);
|
|
ble_buff->skb = skb;
|
|
|
|
return (char *)ble_buff->mem;
|
|
}
|
|
|
|
|
|
int ieee80211_ble_dev_int(struct atbmwifi_common* hw_priv)
|
|
{
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
|
|
ble_local->ble_recv_callback = 0;
|
|
atbm_spin_lock_init(&ble_local->ble_spin_lock);
|
|
atbm_os_mutexLockInit(&ble_local->ble_mutex_lock);
|
|
return 0;
|
|
|
|
}
|
|
int ieee80211_ble_dev_register(struct atbmwifi_common* hw_priv)
|
|
{
|
|
return 0;
|
|
}
|
|
void ieee80211_ble_dev_deregister(struct atbmwifi_common* hw_priv)
|
|
{
|
|
struct ieee80211_ble_local *ble_local = &hw_priv->ble_local;
|
|
|
|
//platform_device_unregister(&local->ble_dev);
|
|
atbm_os_DeleteMutex(&ble_local->ble_mutex_lock);
|
|
}
|
|
#endif
|