linuxOS_D21X/source/linux-5.10/drivers/net/wireless/icommsemi/smac/bdev.c
2024-11-29 16:23:11 +08:00

429 lines
17 KiB
C
Executable File

/*
* Copyright (c) 2015 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.
*/
#include <linux/delay.h>
#include <linux/version.h>
#include <linux/time.h>
#include <linux/kthread.h>
#include "ssv6xxx_common.h"
#ifdef CONFIG_BLE
#if (CONFIG_BLE_HCI_BUS==SSV_BLE_HCI_OVER_SDIO)
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#endif //#if (CONFIG_BLE_HCI_BUS==SSV_BLE_HCI_OVER_SDIO)
#include <ssv6200.h>
#include <hci/hctrl.h>
#include "lib.h"
#include "wow.h"
#include "dev.h"
#include "ap.h"
#include "init.h"
#include "ssv_skb.h"
#include "hw_scan.h"
#include <hal.h>
#include "bdev.h"
extern struct hci_dev *ssv_hdev;;
int ssv_ble_hci_rx_packet(u8 *rx_packet, u32 rx_len)
{
#if (CONFIG_BLE_HCI_BUS == SSV_BLE_HCI_OVER_SDIO)
struct sk_buff *bskb=NULL;
#endif
if(rx_packet[0]==0x04) //Packet Type
{
switch(rx_packet[1])
{
case 0x3E: //LE Event Code
//sub event code
switch(rx_packet[3])
{
case 0x01:printk("BLE RX: LE Connection Complete. len=%d\n",rx_len); break;
case 0x02:printk("BLE RX: LE Advertising Report. len=%d\n",rx_len); break;
case 0x03:printk("BLE RX: LE Connection Update Complete. len=%d\n",rx_len); break;
case 0x04:printk("BLE RX: LE Read Remote Used Features Complete. len=%d\n",rx_len); break;
case 0x05:printk("BLE RX: LE Long Term Key Requested. len=%d\n",rx_len); break;
case 0x06:printk("BLE RX: LE Remote Connection Parameter Request. len=%d\n",rx_len); break;
case 0x07:printk("BLE RX: LE Data Length Change. len=%d\n",rx_len); break;
case 0x08:printk("BLE RX: LE Read Local P256 Public Key Complete. len=%d\n",rx_len); break;
case 0x09:printk("BLE RX: LE Generate DHKey Complete. len=%d\n",rx_len); break;
case 0x0A:printk("BLE RX: LE Enhanced Connection Complete. len=%d\n",rx_len); break;
case 0x0B:printk("BLE RX: LE Direct Advertising Report. len=%d\n",rx_len); break;
default:printk("BLE RX: Unknow sub event (%d)\n",rx_packet[3]); break;
}
break;
//BT Event code
case 0x05:printk("BLE RX: Disconnection Complete. len=%d\n",rx_len); break;
case 0x08:printk("BLE RX: Encryption Change. len=%d\n",rx_len); break;
case 0x0C:printk("BLE RX: Read Remote Version Information Complete. len=%d\n",rx_len); break;
case 0x0E:printk("BLE RX: Command Complete. len=%d\n",rx_len); break;
case 0x0F:printk("BLE RX: Command Status. len=%d\n",rx_len); break;
case 0x10:printk("BLE RX: Hardware Error. len=%d\n",rx_len); break;
case 0x13:printk("BLE RX: Number Of Completed Packets. len=%d\n",rx_len); break;
case 0x1A:printk("BLE RX: Data Buffer Overflow. len=%d\n",rx_len); break;
case 0x30:printk("BLE RX: Encryption Key Refresh Complete. len=%d\n",rx_len); break;
case 0x57:printk("BLE RX: Authenticated Payload Timeout Expired. len=%d\n",rx_len); break;
default:printk("BLE RX: Unknow event (%d)\n",rx_packet[3]); break;
}
}
#if (CONFIG_BLE_HCI_BUS == SSV_BLE_HCI_OVER_SDIO)
/* A SDIO packet is exactly containing a Bluetooth packet */
bskb = bt_skb_alloc(rx_len, GFP_KERNEL);
if (!bskb)
{
return -ENOMEM;
}
skb_put(bskb, rx_len);
memcpy(bskb->data, rx_packet, rx_len);
bt_cb(bskb)->pkt_type = rx_packet[0];
skb_pull(bskb,1);
//_ssv6xxx_hexdump("ble recv pack 1",rx_packet,rx_len);
_ssv6xxx_hexdump("ble recv pack",bskb->data,bskb->len);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
hci_recv_frame(ssv_hdev,bskb);
#else
bskb->dev = (void *)ssv_hdev;
hci_recv_frame(bskb);
#endif
#endif
return 0;
}
#if (CONFIG_BLE_HCI_BUS == SSV_BLE_HCI_OVER_SDIO)
/* ======================== BLE HCI interface ======================== */
extern void _ssv6xxx_hexdump(const char *title, const u8 *buf,
size_t len);
static void ssv_send_ble_packet(struct ssv_softc *sc, u8 *hci_data, u32 len)
{
#if(CONFIG_BLE_HCI_BUS==1) //HCI OVER SDIO
struct sk_buff *skb;
struct cfg_host_cmd *host_cmd;
skb = ssv_skb_alloc(sc,HOST_CMD_HDR_LEN + len);
if(skb == NULL)
{
printk("%s:_skb_alloc fail!!!\n", __func__);
return;
}
skb->data_len = HOST_CMD_HDR_LEN + len;
skb->len = skb->data_len;
host_cmd = (struct cfg_host_cmd *)skb->data;
memset(host_cmd, 0x0, sizeof(struct cfg_host_cmd));
host_cmd->c_type = HOST_CMD;
host_cmd->h_cmd = (u8)SSV6XXX_HOST_CMD_BLE_PACKET;
host_cmd->len = skb->data_len;
memcpy(host_cmd->un.dat8, hci_data, len);
//printk(" ssv6xxx_noa_hdl_bss_change vif_idx[%d]\n", vif_idx);
HCI_SEND(sc->sh, skb, SSV_SW_TXQ_ID_BLE_PDU, false);
#elif (CONFIG_BLE_HCI_BUS==0)
printk(KERN_ERR "\33[31m BLE HCI OVER UART is not implemented\33[0m\r\n");
#else
error
#endif
}
int ssv_ble_hci_flush(struct hci_dev *hdev)
{
struct ssv_softc *sc = hci_get_drvdata(hdev);
printk(KERN_ERR "\33[32m%s():%d\33[0m\r\n",__FUNCTION__ ,__LINE__);
skb_queue_purge(&sc->ble_tx_queue);
return 0;
}
int ssv_ble_hci_open(struct hci_dev *hdev)
{
struct ssv_softc *sc = hci_get_drvdata(hdev);
printk(KERN_ERR "\33[32m%s():%d \33[0m\r\n",__FUNCTION__ ,__LINE__);
HCI_BLE_START(sc->sh);
ssv_ble_init(sc, 0);
return 0;
}
int ssv_ble_hci_close(struct hci_dev *hdev)
{
struct ssv_softc *sc = hci_get_drvdata(hdev);
printk(KERN_ERR "\33[32m%s():%d \33[0m\r\n",__FUNCTION__ ,__LINE__);
ssv_ble_init(sc, 1); // reset fw ble action when call hci close
HCI_BLE_STOP(sc->sh);
HCI_BLE_TXQ_FLUSH(sc->sh);
skb_queue_purge(&sc->ble_tx_queue);
return 0;
}
static u8 ble_rx_packet[512]={0};
int _ssv_ble_process_unknow_hci_opcode(u16 opcode, struct sk_buff *skb)
{
struct ssv_softc *sc = hci_get_drvdata(ssv_hdev);
struct sk_buff *rskb=NULL;
rskb = ssv_skb_alloc(sc,sizeof(ble_rx_packet));
if(NULL==rskb)
{
printk("allocate skb for unknow blc hci cmd fail\n");
return -1;
}
memset(ble_rx_packet,0,sizeof(ble_rx_packet));
switch(opcode)
{
case 0xc14:
ble_rx_packet[0]=0x04;
ble_rx_packet[1]=0x0e;
ble_rx_packet[2]=0xfc;
ble_rx_packet[3]=0x01;
ble_rx_packet[4]=0x14;
ble_rx_packet[5]=0x0c;
ble_rx_packet[6]=0x00;
ble_rx_packet[7]=0x75;
ble_rx_packet[8]=0x62;
ble_rx_packet[9]=0x75;
ble_rx_packet[10]=0x6e;
ble_rx_packet[11]=0x74;
ble_rx_packet[12]=0x75;
ble_rx_packet[13]=0x2d;
ble_rx_packet[14]=0x30;
break;
case 0xc23:
ble_rx_packet[0]=0x04;
ble_rx_packet[1]=0x0e;
ble_rx_packet[2]=0x07;
ble_rx_packet[3]=0x02;
ble_rx_packet[4]=0x23;
ble_rx_packet[5]=0x0c;
ble_rx_packet[6]=0x00;
ble_rx_packet[7]=0x00;
ble_rx_packet[8]=0x01;
ble_rx_packet[9]=0x6c;
break;
default:
printk("host driver doesn't implement this unknow hci cmd\r\n");
return -1;
}
rskb->len=skb->data_len = ble_rx_packet[2]+2;
memcpy(rskb->data,&ble_rx_packet[1],ble_rx_packet[2]+2);
bt_cb(rskb)->pkt_type = ble_rx_packet[0];
_ssv6xxx_hexdump("fake ble hci complete!!",rskb->data,rskb->len);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
hci_recv_frame(ssv_hdev,rskb);
#else
rskb->dev = (void *)ssv_hdev;
hci_recv_frame(rskb);
#endif
return 0;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
int ssv_ble_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
#else
int ssv_ble_hci_send_frame(struct sk_buff *skb)
#endif
{
struct ssv_softc *sc = hci_get_drvdata(ssv_hdev);
u16 opcode=0;
u16 unknow_opcode=0;
if (ssv_hdev == NULL) {
printk(KERN_ERR "\33[32mssv_ble_hci_send_frame ssv_hdev is NULL return \33[0m\r\n");
return 0;
}
//printk(KERN_ERR "\33[32m%s():%d \33[0m\r\n",__FUNCTION__ ,__LINE__);
switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
ssv_hdev->stat.cmd_tx++;
//printk(KERN_ERR "\33[32mHCI_COMMAND_PKT \33[0m\r\n");
break;
case HCI_ACLDATA_PKT:
//hdev->stat.acl_tx++;
printk(KERN_ERR "\33[32mHCI_COMMAND_PKT \33[0m\r\n");
break;
case HCI_SCODATA_PKT:
ssv_hdev->stat.sco_tx++;
//printk(KERN_ERR "\33[32mHCI_SCODATA_PKT \33[0m\r\n");
break;
}
opcode=(skb->data[0]|(skb->data[1]<<8));
//printk("opcode=0x%x\n",opcode);
if((bt_cb(skb)->pkt_type)==HCI_COMMAND_PKT)
{
switch(opcode)
{
case 0x0406:printk("BLE TX: Disconnect\n");break;
case 0x041D:printk("BLE TX: Read Remote Version Information\n");break;
case 0x0C01:printk("BLE TX: Set Event Mask\n");break;
case 0x0C03:printk("BLE TX: Reset\n");break;
case 0x0C2D:printk("BLE TX: Read Transmit Power Level\n");break;
case 0x0C31:printk("BLE TX: Set Controller To Host Flow Control (optional)\n");break;
case 0x0C33:printk("BLE TX: Host Buffer Size (optional)\n");break;
case 0x0C35:printk("BLE TX: Host Number Of Completed Packets (optional)\n");break;
case 0x0C63:printk("BLE TX: Set Event Mask Page\n");break;
case 0x0C7B:printk("BLE TX: Read Authenticated Payload Timeout\n");break;
case 0x0C7C:printk("BLE TX: Write Authenticated Payload Timeout\n");break;
case 0x1001:printk("BLE TX: Read Local Version Information\n");break;
case 0x1002:printk("BLE TX: Read Local Supported Commands -optional-\n");break;
case 0x1003:printk("BLE TX: Read Local Supported Features\n");break;
case 0x1009:printk("BLE TX: Read BD_ADDR\n");break;
case 0x1405:printk("BLE TX: Read RSSI\n");break;
case 0x2001:printk("BLE TX: LE Set Event Mask\n");break;
case 0x2002:printk("BLE TX: LE Read Buffer Size\n");break;
case 0x2003:printk("BLE TX: LE Read Local Supported Features\n");break;
case 0x2005:printk("BLE TX: LE Set Random Address\n");break;
case 0x2006:printk("BLE TX: LE Set Advertising Parameters\n");break;
case 0x2007:printk("BLE TX: LE Read Advertising Channel TX Power\n");break;
case 0x2008:printk("BLE TX: LE Set Advertising Data\n");break;
case 0x2009:printk("BLE TX: LE Set Scan Response Data\n");break;
case 0x200A:printk("BLE TX: LE Set Advertise Enable\n");break;
case 0x200B:printk("BLE TX: LE Set Scan Parameters\n");break;
case 0x200C:printk("BLE TX: LE Set Scan Enable\n");break;
case 0x200D:printk("BLE TX: LE Create Connection\n");break;
case 0x200E:printk("BLE TX: LE Create Connection Cancel\n");break;
case 0x200F:printk("BLE TX: LE Read White List Size\n");break;
case 0x2010:printk("BLE TX: LE Clear White Lis\n");break;
case 0x2011:printk("BLE TX: LE Add Device To White List\n");break;
case 0x2012:printk("BLE TX: LE Remove Device From White List\n");break;
case 0x2013:printk("BLE TX: LE Connection Update\n");break;
case 0x2014:printk("BLE TX: LE Set Host Channel Classification\n");break;
case 0x2015:printk("BLE TX: LE Read Channel Map\n");break;
case 0x2016:printk("BLE TX: LE Read Remote Used Features\n");break;
case 0x2017:printk("BLE TX: LE Encrypt\n");break;
case 0x2018:printk("BLE TX: LE Rand\n");break;
case 0x2019:printk("BLE TX: LE Start Encryption\n");break;
case 0x201A:printk("BLE TX: LE Long Term Key Requested Reply\n");break;
case 0x201B:printk("BLE TX: LE Long Term Key Requested Negative Reply\n");break;
case 0x201C:printk("BLE TX: LE Read Supported States\n");break;
case 0x201D:printk("BLE TX: LE Receiver Test\n");break;
case 0x201E:printk("BLE TX: LE Transmitter Test\n");break;
case 0x201F:printk("BLE TX: LE Test End Command\n");break;
case 0x2020:printk("BLE TX: LE Remote Connection Parameter Request Reply\n");break;
case 0x2021:printk("BLE TX: LE Remote Connection Parameter Request Negative Reply\n");break;
case 0x2022:printk("BLE TX: LE Set Data Length\n");break;
case 0x2023:printk("BLE TX: LE Read Suggested Default Data Length\n");break;
case 0x2024:printk("BLE TX: LE Write Suggested Default Data Length\n");break;
case 0x2026:printk("BLE TX: LE Read Local P256 Public Key 37 0x2025 LE Generate DHKey\n");break;
case 0x2027:printk("BLE TX: LE Add Device to Resolving List\n");break;
case 0x2028:printk("BLE TX: LE Remove Device from Resolving List\n");break;
case 0x2029:printk("BLE TX: LE Clear Resolving List\n");break;
case 0x202A:printk("BLE TX: LE Read Resolving List Size\n");break;
case 0x202B:printk("BLE TX: LE Read Peer Resolvable Address\n");break;
case 0x202C:printk("BLE TX: LE Read Local Resolvable Address\n");break;
case 0x202D:printk("BLE TX: LE Set Address Resolution Enable\n");break;
case 0x202E:printk("BLE TX: LE Set Resolvable Private Address Timeout\n");break;
case 0x202F:printk("BLE TX: LE Read Maximum Data Length\n");break;
default:
//printk("BLE TX: unknow hci cmd 0x%x\n",opcode);
unknow_opcode++;
break;
}
}
if(0!=unknow_opcode)
{
_ssv_ble_process_unknow_hci_opcode(opcode,skb);
goto END;
}
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
_ssv6xxx_hexdump("ble send frame",skb->data,skb->len);
ssv_send_ble_packet(sc,skb->data,skb->len);
END:
skb_queue_tail(&sc->ble_tx_queue, skb);
return 0;
}
#define VENDOR_SPECIFIC_OP 0x3f
#define HCI_SET_BD_ADDR_OP 0x7
int ssv_ble_hci_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
u16 opcode = 0;
u8 cmd[10] = {0};
u8 len = 0;
struct ssv_softc *sc = hci_get_drvdata(ssv_hdev);
if (hdev == NULL || bdaddr == NULL || ssv_hdev == NULL)
return -1;
printk(KERN_ERR "\33[32m%s():%d \33[0m\r\n",__FUNCTION__ ,__LINE__);
opcode = 0;
len = 6;
opcode = ((VENDOR_SPECIFIC_OP << 10) | HCI_SET_BD_ADDR_OP);
cmd[0] = 1;
memcpy(&cmd[1], &opcode, sizeof(opcode));
memcpy(&cmd[1] + sizeof(opcode), &len, sizeof(len));
memcpy(&cmd[1] + sizeof(opcode) + sizeof(len), bdaddr, 6);
printk("set ble addr - %pM\n", bdaddr);
ssv_send_ble_packet(sc, cmd, sizeof(cmd));
return 0;
}
#endif//#if (CONFIG_BLE_HCI_BUS == SSV_BLE_HCI_OVER_SDIO)
void ssv_ble_init(struct ssv_softc *sc, u8 reset_only)
{
struct sk_buff *skb=NULL;
struct cfg_host_cmd *host_cmd;
struct ssv6xxx_ble_config ble_config;
int len=0;
len=sizeof(struct ssv6xxx_ble_config);
memset(&ble_config,0,sizeof(struct ssv6xxx_ble_config));
#if(CONFIG_BLE_HCI_BUS == SSV_BLE_HCI_OVER_SDIO)
printk(KERN_ERR"Config BLE HCI over SDIO\n");
ble_config.bus=SSV_BLE_HCI_OVER_SDIO;
#elif(CONFIG_BLE_HCI_BUS == SSV_BLE_HCI_OVER_UART)
printk(KERN_ERR"Config BLE HCI over UART\n");
ble_config.bus=SSV_BLE_HCI_OVER_UART;
#else
error!
#endif
if (reset_only) {
printk(KERN_ERR"send hci reset\n");
ble_config.hci_reset = 1;
}
ble_config.dtm=sc->sh->cfg.ble_dtm;
memcpy(ble_config.bdaddr, &sc->sh->cfg.maddr[1][0], 6);
ble_config.replace_scan_interval = sc->sh->cfg.ble_replace_scan_interval;
ble_config.replace_scan_win = sc->sh->cfg.ble_replace_scan_win;
skb = ssv_skb_alloc(sc,HOST_CMD_HDR_LEN + len);
if(skb == NULL)
{
printk("%s:_skb_alloc fail!!!\n", __func__);
return;
}
skb->data_len = HOST_CMD_HDR_LEN + len;
skb->len = skb->data_len;
host_cmd = (struct cfg_host_cmd *)skb->data;
memset(host_cmd, 0x0, sizeof(struct cfg_host_cmd));
host_cmd->c_type = HOST_CMD;
host_cmd->h_cmd = (u8)SSV6XXX_HOST_CMD_BLE_INIT;
host_cmd->len = skb->data_len;
memcpy(host_cmd->un.dat8, &ble_config, len);
//printk(" ssv6xxx_noa_hdl_bss_change vif_idx[%d]\n", vif_idx);
HCI_SEND(sc->sh, skb, SSV_SW_TXQ_ID_BLE_PDU, false);
}
#endif//#ifdef CONFIG_BLE