luckfox-pico-sdk/sysdrv/drv_ko/wifi/ssv6115/ble/nimble/nimble_msg.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

197 lines
6.7 KiB
C

/*
* Copyright (c) 2021 iComm-semi Ltd.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* @file fmac_msg_tx.c
* @brief TX function definitions
*/
/*******************************************************************************
* Include Files
******************************************************************************/
#include <linux/version.h>
#include <linux/types.h>
#include "fmac/lmac_types.h"
#include "fmac/fmac.h"
#include "ipc_msg.h"
#include "hci/drv_hci_ops.h"
#include "nimble_msg.h"
#include "ssv_debug.h"
/*******************************************************************************
* Local Defines
******************************************************************************/
/*******************************************************************************
* Local Enumerations
******************************************************************************/
/*******************************************************************************
* Local Structures
******************************************************************************/
/*******************************************************************************
* Global Variables
******************************************************************************/
/*******************************************************************************
* Local Variables
******************************************************************************/
/*******************************************************************************
* Local Functions
******************************************************************************/
static int ssv_ble_drv_hci_tx(struct ssv_nimble_softc *snc, struct sk_buff *skb, int txqid, bool force_trigger, u32 tx_flags)
{
if ((NULL == snc->hci_priv) || (NULL == snc->hci_ops->hci_tx))
return -1;
return snc->hci_ops->hci_tx(snc->hci_priv, skb, txqid, force_trigger, tx_flags);
}
static int ssv_ble_private_msg_to_hci(struct ssv_nimble_softc *snc, u8 *msg_buffer, u32 msg_len)
{
struct sk_buff *skb = NULL;
struct tx_bmu_desc *tx_bmu_hdr = NULL;
struct sdio_hdr *sdio_hdr = NULL;
struct txdesc_api *txdec_hdr = NULL;
u16 headroom = SSV_TX_HDR_SIZE;
u16 frame_len = headroom + msg_len;
u32 frame_oft = 0;
if(1)
{
skb = __dev_alloc_skb(frame_len, GFP_KERNEL);
if (NULL == skb)
{
SSV_LOG_DBG("%s(): Can't alloc skb.\n", __FUNCTION__);
return -1;
}
skb_put(skb, frame_len);
memset((void *)skb->data, 0, skb->len);
/* | |
* |<---------- send to HCI ----------------->|
* | |
* +-------------+----------+------------+--------------------------+
* | tx_bmu_desc | sdio_hdr | txdesc_api | MSDU Frame |
* +-------------+----------+------------+--------------------------+
*
* |<--- skb->data
* |<------------------------ skb->len --------------------------->|
* |
*
*/
/* add tx header and payload */
//build tx_bmu_hdr
tx_bmu_hdr = (struct tx_bmu_desc *)(skb->data);
ssv_build_tx_bmu_header(tx_bmu_hdr, frame_len);
frame_oft += sizeof(struct tx_bmu_desc);
//build sdio_hdr
sdio_hdr =(struct sdio_hdr*)(skb->data+frame_oft);
sdio_hdr->type = E_IPC_TYPE_PRIV_MSG;
sdio_hdr->len = frame_len;
sdio_hdr->queue_idx = 0;
sdio_hdr->reserved = 0;
frame_oft += sizeof(struct sdio_hdr);
//build "empty" txdec_api_hdr
txdec_hdr = (struct txdesc_api*)(skb->data+frame_oft);
frame_oft += sizeof(struct txdesc_api);
//copy msg payload
memcpy((void *)(skb->data+frame_oft), msg_buffer, msg_len);
}
#ifdef CONFIG_HWIF_AND_HCI
return ssv_ble_drv_hci_tx(snc, skb, SSV_SW_TXQ_ID_WIFI_CMD, true, 0);
#else
dev_kfree_skb_any(skb);
return 0;
#endif
}
void ssv_ble_api_send(struct ssv_nimble_softc *snc, char *buf, u16 buflen)
{
ST_IPC_PRIV_MSG *msg = NULL;
u32 msg_total_len = 0;
msg_total_len = (u32)(sizeof(ST_IPC_PRIV_MSG) + buflen);
msg = kzalloc(msg_total_len+1, GFP_KERNEL);
if (!msg) {
SSV_LOG_DBG("%s(): Fail to alloc cmd buffer.\n", __FUNCTION__);
return;
}
// set msg id
msg->msgid = E_IPC_PRIV_MSG_TYPE_NIMBLE_OPS;
msg->msglen = buflen;
memcpy((u8 *)&msg->data[0], (u8 *)buf, buflen);
if (0 > ssv_ble_private_msg_to_hci(snc, (u8*)msg, msg_total_len)) {
SSV_LOG_DBG("Fail to send private command\n");
}
kfree(msg);
}
int ssv_nimble_event(void *app_param, struct sk_buff *skb)
{
//struct ssv_nimble_softc *snc = (struct ssv_nimble_softc *)app_param;
struct rx_info *rx_info = NULL;
u32 *rx_desc = (u32 *)&skb->data[0];
u8 pkt_type = (u8)((*rx_desc) & 0xFF);
//u16 real_pkt_len = (u16)((*rx_desc) >> 8);
skb_pull(skb, 4); //Remove HWIF header(4-bytes).
rx_info = (struct rx_info *)skb->data;
skb_pull(skb, sizeof(struct rx_info)); //Remove HW RX information(84-bytes).
skb_pull(skb, RX_BUF_HEADROOM_SIZE); //Remove SW RX headroom(24-bytes).
if (E_IPC_TYPE_PRIV_MSG == pkt_type) {
ST_IPC_PRIV_MSG *msg = (ST_IPC_PRIV_MSG *)skb->data;
switch(msg->msgid)
{
case E_IPC_PRIV_MSG_TYPE_NIMBLE_EVT:
{
int ssv_ctl_from_ssv_nimble(char *pData, int len);
ssv_ctl_from_ssv_nimble((char *)msg->data, (int)msg->msglen);
dev_kfree_skb_any(skb);
return 0;
}
default:
{
goto unknown_msg;
}
}
}
unknown_msg:
skb_push(skb, RX_BUF_HEADROOM_SIZE); //recovery SW RX headroom(24-bytes).
skb_push(skb, sizeof(struct rx_info)); //recovery HW RX information(84-bytes).
skb_push(skb, 4); //recovery HWIF header(4-bytes).
return -1;
}