Files
LuckFox-RV1103-1106/sysdrv/drv_ko/wifi/aic8800dc/aic8800_fdrv/btsdio.c
T
luckfox-eng29 d2da6f0f4f Add Luckfox Pico 86Panel Support (#274)
* project/cfg/BoardConfig_IPC/overlay : Add Luckfox Pico 86Panel overlay files

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/arch/arm/boot/dts : Add Luckfox Pico 86Panel device tree files

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/cfg/BoardConfig_IPC : Add Luckfox Pico 86Panel BoardConfig files

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/build.sh : Add the lunch menu item of Luckfox Pico 86Panel

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/arch/arm/configs : Add Goodix driver module configuration for RV1106

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* sysdrv/tools/board/buildroot/luckfox_pico_w_defconfig : Add rsync command for Luckfox Pico Buildroot system

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/cfg/BoardConfig_IPC/overlay/overlay-luckfox-ubuntu-config : Add rysnc command for Luckfox Pico Ubuntu system

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/cfg/BoardConfig_IPC/overlay/overlay-luckfox-config/etc/init.d : Add MIC initialization script to improve default recording quality

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* sysdrv/tools/board/buildroot/busybox_patch : ​Add patches to enable Chinese display support in the terminal and allow the reboot command to accept parameters

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* sysdrv/Makefile : Automatically apply BusyBox patches when building the Buildroot image

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/arch/arm/kernel/setup.c : Make the kernel retrieve the unique CPU serial number

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/cfg/BoardConfig_IPC/overlay/overlay-luckfox-config/usr/bin/luckfox-config : Fix errors and add support for eMMC rootfs backup

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* sysdrv/source/kernel/arch/arm/boot/dts : Make Luckfox Pico Ultra and Luckfox Pico Pi default to using i2c4 for CSI cameras

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/cfg/BoardConfig_IPC/overlay/overlay-luckfox-ubuntu-ultra/usr/bin/wifi_bt_init.sh : Enable wireless module initialization support for Ubuntu on Luckfox Pico 86Panel and Luckfox Pico Pi

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/cfg/BoardConfig_IPC : Add executable permission to the BoardConfig scripts

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* sysdrv/source/uboot : Resolve the issue of fast boot failure on certain eMMC models

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/cfg/BoardConfig_IPC/luckfox-rv1106-tb-emmc-post.sh : Resolve the issue of file system initialization failure during eMMC fast boot

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/build.sh : Fix the issue of submodule switch failure

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>

* project/app/rkipc/rkipc/src : Make sure that changes to rkipc.ini can be applied and take effect after modification

Signed-off-by: eng29 <eng29@luckfox.com>

* project/cfg/BoardConfig_IPC : Discontinue support for Ubuntu

Signed-off-by: eng29 <eng29@luckfox.com>

* project/build.sh : Discontinue support for Ubuntu

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/Makefile : Discontinue support for Ubuntu

Signed-off-by: eng29 <eng29@luckfox.com>

* README.md : Update description
README_CN.md : Update description

Signed-off-by: eng29 <eng29@luckfox.com>

* . : Delete the Ubuntu rootfs submodule

Signed-off-by: eng29 <eng29@luckfox.com>

* sysdrv/drv_ko/wifi/aic8800dc : Update the aic8800dc driver

Signed-off-by: eng29 <eng29@luckfox.com>

---------

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
Signed-off-by: eng29 <eng29@luckfox.com>
2025-05-09 14:23:17 +08:00

286 lines
5.8 KiB
C
Executable File

/*
*
* Generic Bluetooth SDIO driver
*
* Copyright (C) 2007 Cambridge Silicon Radio Ltd.
* Copyright (C) 2007 Marcel Holtmann <marcel@holtmann.org>
*
*
* 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/mmc/host.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio_func.h>
#include <net/bluetooth/bluetooth.h>
#include "aic_btsdio.h"
#include "rwnx_msg_tx.h"
#include <net/bluetooth/hci_core.h>
#define VERSION "0.1"
#if CONFIG_BLUEDROID == 0
struct btsdio_data {
struct hci_dev *hdev;
struct work_struct work;
struct sk_buff_head txq;
};
struct hci_dev *ghdev = NULL;
void bt_data_dump(char *tag, void *data, unsigned long len)
{
unsigned long i = 0;
uint8_t *data_ = (uint8_t *)data;
printk("%s %s len:(%lu)\r\n", __func__, tag, len);
for (i = 0; i < len; i += 16) {
printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n",
data_[0 + i], data_[1 + i], data_[2 + i], data_[3 + i],
data_[4 + i], data_[5 + i], data_[6 + i], data_[7 + i],
data_[8 + i], data_[9 + i], data_[10 + i], data_[11 + i],
data_[12 + i], data_[13 + i], data_[14 + i],
data_[15 + i]);
}
}
static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb)
{
int err;
AICBT_INFO("%s", data->hdev->name);
/* Prepend Type-A header */
skb_push(skb, 1);
skb->data[0] = hci_skb_pkt_type(skb);
//bt_data_dump("btwrite", skb->data, skb->len);
err = rwnx_sdio_bt_send_req(g_rwnx_plat->sdiodev->rwnx_hw, skb->len,
skb);
if (err < 0) {
printk("%s rwnx_sdio_bt_send_req error %d", __func__, err);
return err;
}
data->hdev->stat.byte_tx += skb->len;
kfree_skb(skb);
return 0;
}
static void btsdio_work(struct work_struct *work)
{
struct btsdio_data *data = container_of(work, struct btsdio_data, work);
struct sk_buff *skb;
int err;
AICBT_INFO("%s,%s", data->hdev->name, __func__);
while ((skb = skb_dequeue(&data->txq))) {
err = btsdio_tx_packet(data, skb);
if (err < 0) {
data->hdev->stat.err_tx++;
skb_queue_head(&data->txq, skb);
break;
}
}
}
/* Get HCI device by index.
* Device is held on return. */
struct hci_dev *hci_dev_get(int index)
{
if (index != 0)
return NULL;
return ghdev;
}
int bt_sdio_recv(u8 *data, u32 data_len)
{
struct sk_buff *skb;
int type = data[0];
struct hci_dev *hdev;
u32 len = data_len;
int ret = 0;
hdev = hci_dev_get(0);
if (!hdev) {
AICWFDBG(LOGERROR, "%s: Failed to get hci dev[NULL]", __func__);
return -ENODEV;
}
skb = alloc_skb(len - 1, GFP_ATOMIC);
if (!skb) {
AICWFDBG(LOGERROR, "alloc skb fail %s \n", __func__);
}
memcpy(skb_put(skb, len - 1), (data + 1), len - 1);
hdev->stat.byte_rx += len;
hci_skb_pkt_type(skb) = type;
//if(bt_bypass_event(skb)){
//kfree_skb(skb);
///return 0;
//}
AICBT_INFO("skb type %d", type);
//bt_data_dump("bt_skb", skb, skb->len);
ret = hci_recv_frame(hdev, skb);
if (ret < 0) {
AICWFDBG(LOGERROR, "hci_recv_frame fail %d\n", ret);
hdev->stat.err_rx++;
kfree_skb(skb);
}
return 0;
}
static int btsdio_open(struct hci_dev *hdev)
{
//struct btsdio_data *data = hci_get_drvdata(hdev);
int err = 0;
AICBT_INFO("%s", hdev->name);
return err;
}
static int btsdio_close(struct hci_dev *hdev)
{
//struct btsdio_data *data = hci_get_drvdata(hdev);
AICBT_INFO("%s,%s", hdev->name, __func__);
return 0;
}
static int btsdio_flush(struct hci_dev *hdev)
{
struct btsdio_data *data = hci_get_drvdata(hdev);
AICBT_INFO("%s,%s", hdev->name, __func__);
skb_queue_purge(&data->txq);
return 0;
}
static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btsdio_data *data = hci_get_drvdata(hdev);
AICBT_INFO("%s,%s", hdev->name, __func__);
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
case HCI_ACLDATA_PKT:
hdev->stat.acl_tx++;
break;
case HCI_SCODATA_PKT:
hdev->stat.sco_tx++;
break;
default:
return -EILSEQ;
}
skb_queue_tail(&data->txq, skb);
schedule_work(&data->work);
return 0;
}
int btsdio_init(void)
{
struct btsdio_data *data;
struct hci_dev *hdev;
int err;
AICBT_INFO("%s", __func__);
data = kzalloc(sizeof(struct btsdio_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
INIT_WORK(&data->work, btsdio_work);
skb_queue_head_init(&data->txq);
hdev = hci_alloc_dev();
if (!hdev)
return -ENOMEM;
hdev->bus = HCI_SDIO;
hci_set_drvdata(hdev, data);
hdev->dev_type = HCI_PRIMARY;
data->hdev = hdev;
hdev->open = btsdio_open;
hdev->close = btsdio_close;
hdev->flush = btsdio_flush;
hdev->send = btsdio_send_frame;
err = hci_register_dev(hdev);
if (err < 0) {
hci_free_dev(hdev);
return err;
}
ghdev = hdev;
return 0;
}
void btsdio_remove(void)
{
struct btsdio_data *data;
struct hci_dev *hdev;
hdev = hci_dev_get(0);
if (!hdev) {
AICBT_ERR("%s: Failed to get hci dev[Null]", __func__);
return;
}
data = hci_get_drvdata(hdev);
AICBT_INFO("btsdio_remove");
if (!data)
return;
kfree(data);
hci_unregister_dev(hdev);
hci_free_dev(hdev);
}
#endif