/*
*
* Realtek Bluetooth USB driver
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/skbuff.h>
#include <linux/dcache.h>
#include <linux/version.h>
#include <net/sock.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include "rtk_coex.h"
/* Software coex message can be sent to and receive from WiFi driver by
* UDP socket or exported symbol */
/* #define RTK_COEX_OVER_SYMBOL */
#if BTRTL_HCI_IF == BTRTL_HCIUSB
#include <linux/usb.h>
#include "rtk_bt.h"
#undef RTKBT_DBG
#undef RTKBT_INFO
#undef RTKBT_WARN
#undef RTKBT_ERR
#elif BTRTL_HCI_IF == BTRTL_HCIUART
/* #define HCI_VERSION_CODE KERNEL_VERSION(3, 14, 41) */
#define HCI_VERSION_CODE LINUX_VERSION_CODE
#else
#error "Please set type of HCI interface"
#endif
#define RTK_VERSION "1.2"
#define RTKBT_DBG(fmt, arg...) printk(KERN_INFO "rtk_btcoex: " fmt "\n" , ## arg)
#define RTKBT_INFO(fmt, arg...) printk(KERN_INFO "rtk_btcoex: " fmt "\n" , ## arg)
#define RTKBT_WARN(fmt, arg...) printk(KERN_WARNING "rtk_btcoex: " fmt "\n", ## arg)
#define RTKBT_ERR(fmt, arg...) printk(KERN_WARNING "rtk_btcoex: " fmt "\n", ## arg)
static struct rtl_coex_struct btrtl_coex;
#ifdef RTB_SOFTWARE_MAILBOX
#ifdef RTK_COEX_OVER_SYMBOL
static struct sk_buff_head rtw_q;
static struct workqueue_struct *rtw_wq;
static struct work_struct rtw_work;
static u8 rtw_coex_on;
#endif
#endif
#define is_profile_connected(profile) ((btrtl_coex.profile_bitmap & BIT(profile)) > 0)
#define is_profile_busy(profile) ((btrtl_coex.profile_status & BIT(profile)) > 0)
#ifdef RTB_SOFTWARE_MAILBOX
static void rtk_handle_event_from_wifi(uint8_t * msg);
#endif
static int rtl_alloc_buff(struct rtl_coex_struct *coex)
{
struct rtl_hci_ev *ev;
struct rtl_l2_buff *l2;
int i;
int order;
unsigned long addr;
unsigned long addr2;
int ev_size;
int l2_size;
int n;
spin_lock_init(&coex->buff_lock);
INIT_LIST_HEAD(&coex->ev_used_list);
INIT_LIST_HEAD(&coex->ev_free_list);
INIT_LIST_HEAD(&coex->l2_used_list);
INIT_LIST_HEAD(&coex->l2_free_list);
n = NUM_RTL_HCI_EV * sizeof(struct rtl_hci_ev);
ev_size = ALIGN(n, sizeof(unsigned long));
n = L2_MAX_PKTS * sizeof(struct rtl_l2_buff);
l2_size = ALIGN(n, sizeof(unsigned long));
RTKBT_DBG("alloc buffers %d, %d for ev and l2", ev_size, l2_size);
order = get_order(ev_size + l2_size);
addr = __get_free_pages(GFP_KERNEL, order);
if (!addr) {
RTKBT_ERR("failed to alloc buffers for ev and l2.");
return -ENOMEM;
}
memset((void *)addr, 0, ev_size + l2_size);
coex->pages_addr = addr;
coex->buff_size = ev_size + l2_size;
ev = (struct rtl_hci_ev *)addr;
for (i = 0; i < NUM_RTL_HCI_EV; i++) {
list_add_tail(&ev->list, &coex->ev_free_list);
ev++;
}
addr2 = addr + ev_size;
l2 = (struct rtl_l2_buff *)addr2;
for (i = 0; i < L2_MAX_PKTS; i++) {
list_add_tail(&l2->list, &coex->l2_free_list);
l2++;
}
return 0;
}
static void rtl_free_buff(struct rtl_coex_struct *coex)
{
struct rtl_hci_ev *ev;
struct rtl_l2_buff *l2;
unsigned long flags;
spin_lock_irqsave(&coex->buff_lock, flags);
while (!list_empty(&coex->ev_used_list)) {
ev = list_entry(coex->ev_used_list.next, struct rtl_hci_ev,
list);
list_del(&ev->list);
}
while (!list_empty(&coex->ev_free_list)) {
ev = list_entry(coex->ev_free_list.next, struct rtl_hci_ev,
list);
list_del(&ev->list);
}
while (!list_empty(&coex->l2_used_list)) {
l2 = list_entry(coex->l2_used_list.next, struct rtl_l2_buff,
list);
list_del(&l2->list);
}
while (!list_empty(&coex->l2_free_list)) {
l2 = list_entry(coex->l2_free_list.next, struct rtl_l2_buff,
list);
list_del(&l2->list);
}
spin_unlock_irqrestore(&coex->buff_lock, flags);
if (coex->buff_size > 0) {
free_pages(coex->pages_addr, get_order(coex->buff_size));
coex->pages_addr = 0;
coex->buff_size = 0;
}
}
static struct rtl_hci_ev *rtl_ev_node_get(struct rtl_coex_struct *coex)
{
struct rtl_hci_ev *ev;
unsigned long flags;
if (!coex->buff_size)
return NULL;
spin_lock_irqsave(&coex->buff_lock, flags);
if (!list_empty(&coex->ev_free_list)) {
ev = list_entry(coex->ev_free_list.next, struct rtl_hci_ev,
list);
list_del(&ev->list);
} else
ev = NULL;
spin_unlock_irqrestore(&coex->buff_lock, flags);
return ev;
}
static int rtl_ev_node_to_used(struct rtl_coex_struct *coex,
struct rtl_hci_ev *ev)
{
unsigned long flags;
spin_lock_irqsave(&coex->buff_lock, flags);
list_add_tail(&ev->list, &coex->ev_used_list);
spin_unlock_irqrestore(&coex->buff_lock, flags);
return 0;
}
static struct rtl_l2_buff *rtl_l2_node_get(struct rtl_coex_struct *coex)
{
struct rtl_l2_buff *l2;
unsigned long flags;
if (!coex->buff_size)
return NULL;
spin_lock_irqsave(&coex->buff_lock, flags);
if(!list_empty(&coex->l2_free_list)) {
l2 = list_entry(coex->l2_free_list.next, struct rtl_l2_buff,
list);
list_del(&l2->list);
} else
l2 = NULL;
spin_unlock_irqrestore(&coex->buff_lock, flags);
return l2;
}
static int rtl_l2_node_to_used(struct rtl_coex_struct *coex,
struct rtl_l2_buff *l2)
{
unsigned long flags;
spin_lock_irqsave(&coex->buff_lock, flags);
list_add_tail(&l2->list, &coex->l2_used_list);
spin_unlock_irqrestore(&coex->buff_lock, flags);
return 0;
}
static int8_t psm_to_profile_index(uint16_t psm)
{
switch (psm) {
case PSM_AVCTP:
case PSM_SDP:
return -1; //ignore
case PSM_HID:
case PSM_HID_INT:
return profile_hid;
case PSM_AVDTP:
return profile_a2dp;
case PSM_PAN:
case PSM_OPP:
case PSM_FTP:
case PSM_BIP:
case PSM_RFCOMM:
return profile_pan;
default:
return profile_pan;
}
}
static rtk_prof_info *find_by_psm(u16 psm)
{
struct list_head *head = &btrtl_coex.profile_list;
struct list_head *iter = NULL;
struct list_head *temp = NULL;
rtk_prof_info *desc = NULL;
list_for_each_safe(iter, temp, head) {
desc = list_entry(iter, rtk_prof_info, list);
if (desc->psm == psm)
return desc;
}
return NULL;
}
static void rtk_check_setup_timer(int8_t profile_index)
{
if (profile_index == profile_a2dp) {
btrtl_coex.a2dp_packet_count = 0;
btrtl_coex.a2dp_count_timer.expires =
jiffies + msecs_to_jiffies(1000);
mod_timer(&btrtl_coex.a2dp_count_timer,
btrtl_coex.a2dp_count_timer.expires);
}
if (profile_index == profile_pan) {
btrtl_coex.pan_packet_count = 0;
btrtl_coex.pan_count_timer.expires =
jiffies + msecs_to_jiffies(1000);
mod_timer(&btrtl_coex.pan_count_timer,
btrtl_coex.pan_count_timer.expires);
}
/* hogp & voice share one timer now */
if ((profile_index == profile_hogp) || (profile_index == profile_voice)) {
if ((0 == btrtl_coex.profile_refcount[profile_hogp])
&& (0 == btrtl_coex.profile_refcount[profile_voice])) {
btrtl_coex.hogp_packet_count = 0;
btrtl_coex.voice_packet_count = 0;
btrtl_coex.hogp_count_timer.expires =
jiffies + msecs_to_jiffies(1000);
mod_timer(&btrtl_coex.hogp_count_timer,
btrtl_coex.hogp_count_timer.expires);
}
}
}
static void rtk_check_del_timer(int8_t profile_index)
{
if (profile_a2dp == profile_index) {
btrtl_coex.a2dp_packet_count = 0;
del_timer_sync(&btrtl_coex.a2
Serein朔一
- 粉丝: 112
- 资源: 4
最新资源
- 网上书城系统(Struts+Hibernate+Mysql).rar
- 网上书店(struts+hibernate+css+mysql).rar
- 网上书店系统(论文+jsp源程序)130220.rar
- 网上书店系统(论文+jsp源程序).rar
- 网上书店(struts+hibernate+css+mysql)130223.rar
- 系统详细配置方法.rar
- 文本编辑器.rar
- 项目申报系统(Struts2+Spring+Hibernate+Jsp+Mysql5).rar
- 纯电动汽车再生制动策略,Cruise和Simulink联合仿真,提供Cruise整车模型和simuink策略模型,有详细解析文档,可运行
- 学生成绩管理系统(SSH+MYSQL)130221.rar
- 学生成绩管理系统(SSH+MYSQL).rar
- 项目申报系统(Struts2+Spring+Hibernate+Jsp+Mysql5)130223.rar
- 移动ssh项目(struts+spring+hibernate+oracle).rar
- 阳光酒店管理系统(javaapplet+SQL)130425.rar
- 移动ssh项目(struts+spring+hibernate+oracle)130222.rar
- 音乐网站(JSP+SERVLET)130222.rar
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈