Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/next/external/cache/sources/hcitools/hciattach_rtk.c
Views: 3959
/*1*2* BlueZ - Bluetooth protocol stack for Linux3*4* Copyright (C) 2005-2010 Marcel Holtmann <[email protected]>5* Copyright (C) 2013-2014 Realtek Semiconductor Corp.6*7*8* This program is free software; you can redistribute it and/or modify9* it under the terms of the GNU General Public License as published by10* the Free Software Foundation; either version 2 of the License, or11* (at your option) any later version.12*13* This program is distributed in the hope that it will be useful,14* but WITHOUT ANY WARRANTY; without even the implied warranty of15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the16* GNU General Public License for more details.17*18* You should have received a copy of the GNU General Public License19* along with this program; if not, write to the Free Software20* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA21*22*/2324#ifdef HAVE_CONFIG_H25#include <config.h>26#endif2728#include <stdio.h>29#include <errno.h>30#include <unistd.h>31#include <stdlib.h>32#include <termios.h>33#include <time.h>34#include <sys/time.h>35#include <sys/types.h>36#include <sys/param.h>37#include <sys/ioctl.h>38#include <sys/socket.h>39#include <sys/uio.h>40#include <sys/stat.h>41#include <fcntl.h>4243#include <signal.h>44#define Config_Android 0 /*1 for android; 0 for Linux*/4546#if Config_Android //for Android47#include <bluetooth/bluetooth.h>48#include <bluetooth/hci.h>49#include <bluetooth/hci_lib.h>50#else //for Linux51#include <stdint.h>52#include <string.h>53#include <endian.h>54#include <byteswap.h>55#include <netinet/in.h>56#endif5758#include "hciattach.h"5960#define BAUDRATE_4BYTES61#define RTK_VERSION "2.3"62#if __BYTE_ORDER == __LITTLE_ENDIAN63#define cpu_to_le16(d) (d)64#define cpu_to_le32(d) (d)65#define le16_to_cpu(d) (d)66#define le32_to_cpu(d) (d)67#elif __BYTE_ORDER == __BIG_ENDIAN68#define cpu_to_le16(d) bswap_16(d)69#define cpu_to_le32(d) bswap_32(d)70#define le16_to_cpu(d) bswap_16(d)71#define le32_to_cpu(d) bswap_32(d)72#else73#error "Unknown byte order"74#endif7576/* log related */77#define LOG_STR "Realtek Bluetooth"78#define DBG_ON 17980#define RS_DBG(fmt, arg...) \81do { \82if (DBG_ON) \83fprintf(stderr, "%s: " fmt "\n", LOG_STR, ##arg); \84} while (0)8586#define RS_ERR(fmt, arg...) \87do { \88fprintf(stderr, "%s ERROR: " fmt "\n", LOG_STR, ##arg);\89perror("reason: "); \90} while (0)9192#define RS_DUMP(buffer, len) \93do { \94fprintf(stderr, "%s: ", LOG_STR); \95for (int i = 0; i < len; i++) { \96if (i && !(i % 16)) { \97fprintf(stderr, "\n"); \98fprintf(stderr, "%s: ", LOG_STR); \99} \100fprintf(stderr, "%02x ", buffer[i]); \101} \102fprintf(stderr, "\n"); \103} while (0)104105struct sk_buff {106uint32_t max_len;107uint32_t data_len;108uint8_t data[0];109};110111/* Skb helpers */112struct bt_skb_cb {113uint8_t pkt_type;114uint8_t incoming;115uint16_t expect;116uint8_t tx_seq;117uint8_t retries;118uint8_t sar;119uint16_t channel;120};121122typedef struct {123uint8_t index;124uint8_t data[252];125} __attribute__ ((packed)) download_vendor_patch_cp;126127struct hci_command_hdr {128uint16_t opcode; /* OCF & OGF */129uint8_t plen;130} __attribute__ ((packed));131132struct hci_event_hdr {133uint8_t evt;134uint8_t plen;135} __attribute__ ((packed));136137struct hci_ev_cmd_complete {138uint8_t ncmd;139uint16_t opcode;140} __attribute__ ((packed));141142#define HCI_COMMAND_HDR_SIZE 3143#define HCI_EVENT_HDR_SIZE 2144145#define HCI_CMD_READ_BD_ADDR 0x1009146#define HCI_VENDOR_CHANGE_BDRATE 0xfc17147#define HCI_VENDOR_READ_RTK_ROM_VERISION 0xfc6d148#define HCI_VENDOR_READ_LMP_VERISION 0x1001149#define HCI_VENDOR_READ_CHIP_TYPE 0xfc61150151#define ROM_LMP_8723a 0x1200152153#define RTK_VENDOR_CONFIG_MAGIC 0x8723ab55154155#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))156157#if Config_Android158#define FIRMWARE_DIRECTORY "/system/vendor/etc/firmware"159#define BT_CONFIG_DIRECTORY "/system/vendor/etc/firmware"160#else161#define FIRMWARE_DIRECTORY "/system/vendor/etc/firmware"162#define BT_CONFIG_DIRECTORY "/system/vendor/etc/firmware"163#endif164165#define BT_ADDR_DIR "/data/misc/bluetooth/"166#define BT_ADDR_FILE "/data/misc/bluetooth/btmac.txt"167168#define PATCH_DATA_FIELD_MAX_SIZE 252169#define READ_DATA_SIZE 16170171/* HCI data types */172#define H5_ACK_PKT 0x00173#define HCI_COMMAND_PKT 0x01174#define HCI_ACLDATA_PKT 0x02175#define HCI_SCODATA_PKT 0x03176#define HCI_EVENT_PKT 0x04177#define H5_VDRSPEC_PKT 0x0E178#define H5_LINK_CTL_PKT 0x0F179180181#define HCI_VERSION_MASK_10 (1<<0) // Bluetooth Core Spec 1.0b182#define HCI_VERSION_MASK_11 (1<<1) // Bluetooth Core Spec 1.1183#define HCI_VERSION_MASK_12 (1<<2) // Bluetooth Core Spec 1.2184#define HCI_VERSION_MASK_20 (1<<3) // Bluetooth Core Spec 2.0+EDR185#define HCI_VERSION_MASK_21 (1<<4) // Bluetooth Core Spec 2.1+EDR186#define HCI_VERSION_MASK_30 (1<<5) // Bluetooth Core Spec 3.0+HS187#define HCI_VERSION_MASK_40 (1<<6) // Bluetooth Core Spec 4.0188#define HCI_VERSION_MASK_41 (1<<7) // Bluetooth Core Spec 4.1189#define HCI_VERSION_MASK_42 (1<<8) // Bluetooth Core Spec 4.2190#define HCI_VERSION_MASK_ALL (0xFFFFFFFF)191192#define HCI_REVISION_MASK_ALL (0xFFFFFFFF)193194#define LMP_SUBVERSION_NONE (0x0)195196#define CHIPTYPE_NONE (0x1F) // Chip Type's range: 0x0 ~ 0xF197#define CHIP_TYPE_MASK_ALL (0xFFFFFFFF)198199#define PROJECT_ID_MASK_ALL (0xFFFFFFFF) // temp used for unknow project id for a new chip200201#define CONFIG_MAC_OFFSET_GEN_1_2 (0x3C) // MAC's OFFSET in config/efuse for realtek generation 1~2 bluetooth chip202#define CONFIG_MAC_OFFSET_GEN_3PLUS (0x44) // MAC's OFFSET in config/efuse for rtk generation 3+ bluetooth chip203#define CONFIG_MAC_OFFSET_GEN_4PLUS (0x30) // MAC's OFFSET in config/efuse for rtk generation 4+ bluetooth chip204205#define PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE (0x1)206207#define MAX_PATCH_SIZE_24K (1024*24) // 24K208#define MAX_PATCH_SIZE_40K (1024*40) // 40K209210struct rtk_bt_vendor_config_entry {211uint16_t offset;212uint8_t entry_len;213uint8_t entry_data[0];214} __attribute__ ((packed));215216struct rtk_bt_vendor_config {217uint32_t signature;218uint16_t data_len;219struct rtk_bt_vendor_config_entry entry[0];220} __attribute__ ((packed));221222struct rtk_epatch_entry {223uint16_t chipID;224uint16_t patch_length;225uint32_t start_offset;226} __attribute__ ((packed));227228struct rtk_epatch {229uint8_t signature[8];230uint32_t fm_version;231uint16_t number_of_total_patch;232struct rtk_epatch_entry entry[0];233} __attribute__ ((packed));234235typedef enum _RTK_ROM_VERSION_CMD_STATE {236cmd_not_send,237cmd_has_sent,238event_received239} RTK_ROM_VERSION_CMD_STATE;240241#pragma pack(1)242#if __BYTE_ORDER == __LITTLE_ENDIAN243typedef struct _H5_PKT_HEADER {244uint8_t SeqNumber:3;245uint8_t AckNumber:3;246uint8_t DicPresent:1; /* Data Integrity Check Present */247uint8_t ReliablePkt:1;248uint16_t PktType:4;249uint16_t PayloadLen:12;250uint8_t HdrChecksum;251} H5_PKT_HEADER;252#else253typedef struct _H5_PKT_HEADER {254uint8_t ReliablePkt:1;255uint8_t DicPresent:1; /* Data Integrity Check Present */256uint8_t AckNumber:3;257uint8_t SeqNumber:3;258uint16_t PayloadLen:12;259uint16_t PktType:4;260uint8_t HdrChecksum;261} H5_PKT_HEADER;262#endif263264typedef enum _H5_RX_STATE {265H5_W4_PKT_DELIMITER,266H5_W4_PKT_START,267H5_W4_HDR,268H5_W4_DATA,269H5_W4_CRC270} H5_RX_STATE;271272typedef enum _H5_RX_ESC_STATE {273H5_ESCSTATE_NOESC,274H5_ESCSTATE_ESC275} H5_RX_ESC_STATE;276277typedef enum _H5_LINK_STATE {278H5_SYNC,279H5_CONFIG,280H5_INIT,281H5_PATCH,282H5_ACTIVE283} H5_LINK_STATE;284285typedef enum _PATCH_PROTOCOL {286PATCH_PROTOCAL_H4,287PATCH_PROTOCAL_H5288} PATCH_PROTOCOL;289290struct rtk_h5_struct {291uint8_t rxseq_txack; /* rxseq == txack. expected rx SeqNumber */292uint8_t rxack; /* Last packet sent by us that the peer ack'ed */293uint8_t use_crc;294uint8_t is_txack_req; /* txack required? Do we need to send ack's to the peer? */295/* Reliable packet sequence number - used to assign seq to each rel pkt. */296uint8_t msgq_txseq; /* next pkt seq */297uint16_t message_crc;298uint32_t rx_count; /* expected pkts to recv */299H5_RX_STATE rx_state;300H5_RX_ESC_STATE rx_esc_state;301H5_LINK_STATE link_estab_state;302struct sk_buff *rx_skb;303struct sk_buff *host_last_cmd;304};305306struct patch_struct {307int nTxIndex; /* current sending pkt number */308int nTotal; /* total pkt number */309int nRxIndex; /* ack index from board */310int nNeedRetry; /* if no response from board */311};312313typedef struct {314uint16_t lmp_subversion;315uint32_t hci_version_mask;316uint32_t hci_revision_mask;317uint32_t chip_type_mask;318uint32_t project_id_mask;319char *patch_name;320char *config_name;321uint16_t mac_offset;322uint32_t max_patch_size;323} patch_info;324325/* h/w config control block */326typedef struct {327uint32_t max_patch_size;328uint32_t baudrate;329uint16_t lmp_subversion;330uint16_t lmp_subversion_default;331uint16_t lmp_sub_current;332uint8_t state; /* Hardware configuration state */333uint8_t eversion;334uint32_t project_id_mask;335uint8_t hci_version;336uint8_t hci_revision;337uint8_t chip_type;338} bt_hw_cfg_cb_t;339340static patch_info patch_table[] = {341/* lmp_subv hci_version_mask hci_revision_mask chip_type_mask project_id_mask fw name config name mac offset max_patch_size */342{0x1200, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<0, "rtl8723as_fw", "rtl8723as_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8723AS343#ifdef RTL_8723BS_BT_USED344{0x8723, ~(HCI_VERSION_MASK_21), ~(1<<0xd), CHIP_TYPE_MASK_ALL, 1<<1, "rtl8723bs_fw", "rtl8723bs_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8723BS345#else346{0x8723, ~(HCI_VERSION_MASK_21), ~(1<<0xd), CHIP_TYPE_MASK_ALL, 1<<1, "rtl8723bs_VQ0_fw", "rtl8723bs_VQ0_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8723BS_VQ0347#endif348{0x8821, HCI_VERSION_MASK_ALL, ~(1<<0xc), CHIP_TYPE_MASK_ALL, 1<<2, "rtl8821as_fw", "rtl8821as_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8821AS349/* {0x8761, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<3, "rtl8761at_fw", "rtl8761at_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8761AW */350{0x8761, HCI_VERSION_MASK_ALL, ~(1<<0xb), CHIP_TYPE_MASK_ALL, 1<<3, "rtl8761at_fw", "rtl8761at_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8761AW351{0x8761, HCI_VERSION_MASK_ALL, (1<<0xb), CHIP_TYPE_MASK_ALL, 1<<14, "rtl8761bt_fw", "rtl8761bt_config", CONFIG_MAC_OFFSET_GEN_4PLUS, MAX_PATCH_SIZE_40K}, //Rtl8761BW352353{0x8723, HCI_VERSION_MASK_21, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<4, "rtl8703as_fw", "rtl8703as_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8703AS354355{0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<7, 1<<6, "rtl8703bs_fw", "rtl8703bs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //Rtl8703BS356{0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<5, 1<<7, "rtl8723cs_xx_fw", "rtl8723cs_xx_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //rtl8723cs_xx357{0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<3, 1<<7, "rtl8723cs_cg_fw", "rtl8723cs_cg_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //rtl8723cs_cg358{0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<4, 1<<7, "rtl8723cs_vf_fw", "rtl8723cs_vf_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //rtl8723cs_vf359/* {0x8822, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<8, "rtl8822bs_fw", "rtl8822bs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //Rtl8822BS */360{0x8822, HCI_VERSION_MASK_ALL, ~(1<<0xc), CHIP_TYPE_MASK_ALL, 1<<8, "rtl8822bs_fw", "rtl8822bs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //Rtl8822BS361{0x8822, HCI_VERSION_MASK_ALL, (1<<0xc), CHIP_TYPE_MASK_ALL, 1<<13, "rtl8822cs_fw", "rtl8822cs_config", CONFIG_MAC_OFFSET_GEN_4PLUS, MAX_PATCH_SIZE_40K}, //Rtl8822CS362363{0x8723, HCI_VERSION_MASK_ALL, (1<<0xd), ~(1<<7), 1<<9, "rtl8723ds_fw", "rtl8723ds_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, //Rtl8723ds364{0x8723, HCI_VERSION_MASK_ALL, (1<<0xd), 1<<7, 1<<9, "rtl8703cs_fw", "rtl8703cs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, //Rtl8703cs365{0x8821, HCI_VERSION_MASK_ALL, (1<<0xc), CHIP_TYPE_MASK_ALL, 1<<10, "rtl8821cs_fw", "rtl8821cs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, //RTL8821CS366/* todo: RTL8703CS */367{LMP_SUBVERSION_NONE, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, PROJECT_ID_MASK_ALL, "rtl_none_fw", "rtl_none_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}368};369370static bt_hw_cfg_cb_t hw_cfg_cb;371static uint8_t gEVersion;372static RTK_ROM_VERSION_CMD_STATE gRom_version_cmd_state;373static RTK_ROM_VERSION_CMD_STATE ghci_version_cmd_state;374static RTK_ROM_VERSION_CMD_STATE gchip_type_cmd_state;375static int gHwFlowControlEnable;376static int gFinalSpeed;377378/* signature: Realtech */379static const uint8_t RTK_EPATCH_SIGNATURE[8] = {0x52, 0x65, 0x61, 0x6C, 0x74, 0x65, 0x63, 0x68};380/* Extension Section IGNATURE:0x77FD0451 */381static const uint8_t Extension_Section_SIGNATURE[4] = {0x51, 0x04, 0xFD, 0x77};382383static int serial_fd;384static int h5_max_retries = 40;385static struct rtk_h5_struct rtk_h5;386static struct patch_struct rtk_patch;387388/* bite reverse in bytes38900000001 -> 1000000039000000100 -> 00100000391*/392static const uint8_t byte_rev_table[256] = {3930x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,3940x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,3950x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,3960x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,3970x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,3980x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,3990x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,4000x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,4010x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,4020x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,4030x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,4040x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,4050x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,4060x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,4070x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,4080x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,4090x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,4100x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,4110x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,4120x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,4130x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,4140x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,4150x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,4160x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,4170x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,4180x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,4190x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,4200x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,4210x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,4220x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,4230x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,4240x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,425};426427/* reverse bit */428static __inline uint8_t bit_rev8(uint8_t byte)429{430return byte_rev_table[byte];431}432433/* reverse bit */434static __inline uint16_t bit_rev16(uint16_t x)435{436return (bit_rev8(x & 0xff) << 8) | bit_rev8(x >> 8);437}438439static const uint16_t crc_table[] = {4400x0000, 0x1081, 0x2102, 0x3183,4410x4204, 0x5285, 0x6306, 0x7387,4420x8408, 0x9489, 0xa50a, 0xb58b,4430xc60c, 0xd68d, 0xe70e, 0xf78f444};445446/**447* Malloc the socket buffer448*449* @param skb socket buffer450* @return the point to the malloc buffer451*/452static __inline struct sk_buff *skb_alloc(uint32_t len)453{454struct sk_buff *skb = NULL;455skb = malloc(len + 8);456if (skb) {457skb->max_len = len;458skb->data_len = 0;459memset(skb->data, 0, len);460} else {461RS_ERR("Allocate skb fails!!!");462skb = NULL;463}464return skb;465}466467/**468* Free the socket buffer469*470* @param skb socket buffer471*/472static __inline void skb_free(struct sk_buff *skb)473{474free(skb);475return;476}477478/**479* Increase the date length in sk_buffer by len,480* and return the increased header pointer481*482* @param skb socket buffer483* @param len length want to increase484* @return the pointer to increased header485*/486static uint8_t *skb_put(struct sk_buff *skb, uint32_t len)487{488uint32_t old_len = skb->data_len;489if ((skb->data_len + len) > (skb->max_len)) {490RS_ERR("Buffer too small");491return NULL;492}493skb->data_len += len;494return (skb->data + old_len);495}496497/**498* decrease data length in sk_buffer by to len by cut the tail499*500* @warning len should be less than skb->len501*502* @param skb socket buffer503* @param len length want to be changed504*/505static void skb_trim(struct sk_buff *skb, int len)506{507if (skb->data_len > len) {508skb->data_len = len;509} else {510RS_ERR("Error: skb->data_len(%ld) < len(%d)", (long int)skb->data_len, len);511}512}513514/**515* Decrease the data length in sk_buffer by len,516* and move the content forward to the header.517* the data in header will be removed.518*519* @param skb socket buffer520* @param len length of data521* @return new data522*/523static uint8_t *skb_pull(struct sk_buff *skb, uint32_t len)524{525skb->data_len -= len;526char *buf;527buf = malloc(skb->data_len);528if (!buf) {529RS_ERR("Unable to allocate file buffer");530exit(1);531}532memcpy(buf, skb->data+len, skb->data_len);533memcpy(skb->data, buf, skb->data_len);534free(buf);535return skb->data;536}537538/**539* Add "d" into crc scope, caculate the new crc value540*541* @param crc crc data542* @param d one byte data543*/544static void h5_crc_update(uint16_t *crc, uint8_t d)545{546uint16_t reg = *crc;547548reg = (reg >> 4) ^ crc_table[(reg ^ d) & 0x000f];549reg = (reg >> 4) ^ crc_table[(reg ^ (d >> 4)) & 0x000f];550551*crc = reg;552}553554struct __una_u16 { uint16_t x; };555556static __inline uint16_t __get_unaligned_cpu16(const void *p)557{558const struct __una_u16 *ptr = (const struct __una_u16 *)p;559return ptr->x;560}561562static __inline uint16_t get_unaligned_be16(const void *p)563{564return __get_unaligned_cpu16((const uint8_t *)p);565}566567/**568* Get crc data.569*570* @param h5 realtek h5 struct571* @return crc data572*/573static uint16_t h5_get_crc(struct rtk_h5_struct *h5)574{575uint16_t crc = 0;576uint8_t *data = h5->rx_skb->data + h5->rx_skb->data_len - 2;577crc = data[1] + (data[0] << 8);578return crc;579}580581/**582* Just add 0xc0 at the end of skb,583* we can also use this to add 0xc0 at start while there is no data in skb584*585* @param skb socket buffer586*/587static void h5_slip_msgdelim(struct sk_buff *skb)588{589const char pkt_delim = 0xc0;590memcpy(skb_put(skb, 1), &pkt_delim, 1);591}592593/**594* Slip ecode one byte in h5 proto, as follows:595* 0xc0 -> 0xdb, 0xdc596* 0xdb -> 0xdb, 0xdd597* 0x11 -> 0xdb, 0xde598* 0x13 -> 0xdb, 0xdf599* others will not change600*601* @param skb socket buffer602* @c pure data in the one byte603*/604static void h5_slip_one_byte(struct sk_buff *skb, uint8_t c)605{606const int8_t esc_c0[2] = { 0xdb, 0xdc };607const int8_t esc_db[2] = { 0xdb, 0xdd };608const int8_t esc_11[2] = { 0xdb, 0xde };609const int8_t esc_13[2] = { 0xdb, 0xdf };610611switch (c) {612case 0xc0:613memcpy(skb_put(skb, 2), &esc_c0, 2);614break;615case 0xdb:616memcpy(skb_put(skb, 2), &esc_db, 2);617break;618case 0x11:619memcpy(skb_put(skb, 2), &esc_11, 2);620break;621case 0x13:622memcpy(skb_put(skb, 2), &esc_13, 2);623break;624default:625memcpy(skb_put(skb, 1), &c, 1);626}627}628629/**630* Decode one byte in h5 proto, as follows:631* 0xdb, 0xdc -> 0xc0632* 0xdb, 0xdd -> 0xdb633* 0xdb, 0xde -> 0x11634* 0xdb, 0xdf -> 0x13635* others will not change636*637* @param h5 realtek h5 struct638* @byte pure data in the one byte639*/640static void h5_unslip_one_byte(struct rtk_h5_struct *h5, char byte)641{642const uint8_t c0 = 0xc0, db = 0xdb;643const uint8_t oof1 = 0x11, oof2 = 0x13;644//RS_DBG("HCI 3wire h5_unslip_one_byte");645646if (H5_ESCSTATE_NOESC == h5->rx_esc_state) {647if (0xdb == byte) {648h5->rx_esc_state = H5_ESCSTATE_ESC;649} else {650memcpy(skb_put(h5->rx_skb, 1), &byte, 1);651//Check Pkt Header's CRC enable bit652if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC) {653h5_crc_update(&h5->message_crc, byte);654}655h5->rx_count--;656}657} else if (H5_ESCSTATE_ESC == h5->rx_esc_state) {658switch (byte) {659case 0xdc:660memcpy(skb_put(h5->rx_skb, 1), &c0, 1);661if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)662h5_crc_update(&h5->message_crc, 0xc0);663h5->rx_esc_state = H5_ESCSTATE_NOESC;664h5->rx_count--;665break;666case 0xdd:667memcpy(skb_put(h5->rx_skb, 1), &db, 1);668if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)669h5_crc_update(&h5->message_crc, 0xdb);670h5->rx_esc_state = H5_ESCSTATE_NOESC;671h5->rx_count--;672break;673case 0xde:674memcpy(skb_put(h5->rx_skb, 1), &oof1, 1);675if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)676h5_crc_update(&h5->message_crc, oof1);677h5->rx_esc_state = H5_ESCSTATE_NOESC;678h5->rx_count--;679break;680case 0xdf:681memcpy(skb_put(h5->rx_skb, 1), &oof2, 1);682if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)683h5_crc_update(&h5->message_crc, oof2);684h5->rx_esc_state = H5_ESCSTATE_NOESC;685h5->rx_count--;686break;687default:688RS_ERR("Error: Invalid byte %02x after esc byte", byte);689skb_free(h5->rx_skb);690h5->rx_skb = NULL;691h5->rx_state = H5_W4_PKT_DELIMITER;692h5->rx_count = 0;693break;694}695}696}697698/**699* Prepare h5 packet, packet format as follow:700* | LSB 4 octets | 0 ~ 4095 | 2 MSB701* |packet header | payload | data integrity check |702*703* pakcket header fromat is show below:704* | LSB 3 bits | 3 bits | 1 bits | 1 bits |705* | 4 bits | 12 bits | 8 bits MSB706* |sequence number | acknowledgement number | data integrity check present | reliable packet |707* |packet type | payload length | header checksum708*709* @param h5 realtek h5 struct710* @param data pure data711* @param len the length of data712* @param pkt_type packet type713* @return socket buff after prepare in h5 proto714*/715static struct sk_buff *h5_prepare_pkt(struct rtk_h5_struct *h5, uint8_t *data, int32_t len, int32_t pkt_type)716{717struct sk_buff *nskb;718uint8_t hdr[4];719uint16_t h5_txmsg_crc = 0xffff;720int rel, i;721722switch (pkt_type) {723case HCI_ACLDATA_PKT:724case HCI_COMMAND_PKT:725case HCI_EVENT_PKT:726rel = 1; /* reliable */727break;728case H5_ACK_PKT:729case H5_VDRSPEC_PKT:730case H5_LINK_CTL_PKT:731rel = 0; /* unreliable */732break;733default:734RS_ERR("Unknown packet type");735return NULL;736}737738/* Max len of packet: (original len +4(h5 hdr) + 2(crc)) * 2739* (because bytes 0xc0 and 0xdb are escaped, worst case is740* when the packet is all made of 0xc0 and 0xdb :))741* + 2 (0xc0 delimiters at start and end). */742nskb = skb_alloc((len + 6) * 2 + 2);743if (!nskb)744return NULL;745746/* Add SLIP start byte: 0xc0 */747h5_slip_msgdelim(nskb);748/* set AckNumber in SlipHeader */749hdr[0] = h5->rxseq_txack << 3;750h5->is_txack_req = 0;751752if (rel) {753/* set reliable pkt bit and SeqNumber */754hdr[0] |= 0x80 + h5->msgq_txseq;755++(h5->msgq_txseq);756h5->msgq_txseq = (h5->msgq_txseq) & 0x07;757}758759/* set DicPresent bit */760if (h5->use_crc)761hdr[0] |= 0x40;762763/* set packet type and payload length */764hdr[1] = ((len << 4) & 0xff) | pkt_type;765hdr[2] = (uint8_t)(len >> 4);766/* set checksum */767hdr[3] = ~(hdr[0] + hdr[1] + hdr[2]);768769/* Put h5 header */770for (i = 0; i < 4; i++) {771h5_slip_one_byte(nskb, hdr[i]);772773if (h5->use_crc)774h5_crc_update(&h5_txmsg_crc, hdr[i]);775}776777/* Put payload */778for (i = 0; i < len; i++) {779h5_slip_one_byte(nskb, data[i]);780781if (h5->use_crc)782h5_crc_update(&h5_txmsg_crc, data[i]);783}784785/* Put CRC */786if (h5->use_crc) {787h5_txmsg_crc = bit_rev16(h5_txmsg_crc);788h5_slip_one_byte(nskb, (uint8_t) ((h5_txmsg_crc >> 8) & 0x00ff));789h5_slip_one_byte(nskb, (uint8_t) (h5_txmsg_crc & 0x00ff));790}791792/* Add SLIP end byte: 0xc0 */793h5_slip_msgdelim(nskb);794return nskb;795}796797/**798* Removed controller acked packet from Host's unacked lists799*800* @param h5 realtek h5 struct801*/802static void h5_remove_acked_pkt(struct rtk_h5_struct *h5)803{804int pkts_to_be_removed = 0;805int seqno = 0;806int i = 0;807808seqno = h5->msgq_txseq;809810while (pkts_to_be_removed) {811if (h5->rxack == seqno)812break;813814pkts_to_be_removed--;815seqno = (seqno - 1) & 0x07;816}817818if (h5->rxack != seqno) {819RS_DBG("Peer acked invalid packet");820}821822i = 0;823for (i = 0; i < 5; ++i) {824if (i >= pkts_to_be_removed)825break;826i++;827}828829if (i != pkts_to_be_removed)830RS_DBG("Removed only (%d) out of (%d) pkts", i, pkts_to_be_removed);831}832833/**834* Realtek send pure ack, send a packet only with an ack835*836* @param fd uart file descriptor837*838*/839static void rtk_send_pure_ack_down(int fd)840{841struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, NULL, 0, H5_ACK_PKT);842write(fd, nskb->data, nskb->data_len);843skb_free(nskb);844return;845}846847/**848* Parse hci event command complete, pull the cmd complete event header849*850* @param skb socket buffer851*852*/853static void hci_event_cmd_complete(struct sk_buff *skb)854{855struct hci_ev_cmd_complete *ev = NULL;856uint16_t opcode = 0;857uint8_t status = 0;858859/* omit length check */860/* pull hdr */861skb_pull(skb, HCI_EVENT_HDR_SIZE);862ev = (struct hci_ev_cmd_complete *)skb->data;863opcode = le16_to_cpu(ev->opcode);864865RS_DBG("receive hci command complete event with command: %x", opcode);866if (DBG_ON) {867RS_DBG("Dump event data with event header (header size %d):", sizeof(struct hci_ev_cmd_complete));868RS_DUMP(skb->data, skb->data_len);869}870871/* pull command complete event header */872skb_pull(skb, sizeof(struct hci_ev_cmd_complete));873874switch (opcode) {875case HCI_VENDOR_CHANGE_BDRATE:876status = skb->data[0];877RS_DBG("Change BD Rate with status:%x", status);878skb_free(rtk_h5.host_last_cmd);879rtk_h5.host_last_cmd = NULL;880rtk_h5.link_estab_state = H5_PATCH;881break;882case HCI_CMD_READ_BD_ADDR:883status = skb->data[0];884RS_DBG("Read BD Address with Status:%x", status);885if (!status) {886RS_DBG("BD Address: %8x%8x", *(int *)&skb->data[1], *(int *)&skb->data[5]);887}888break;889case HCI_VENDOR_READ_LMP_VERISION:890ghci_version_cmd_state = event_received;891status = skb->data[0];892RS_DBG("Read RTK LMP version with Status:%x", status);893if (0 == status) {894hw_cfg_cb.hci_version = *(uint8_t *)(&skb->data[1]);895hw_cfg_cb.hci_revision = *(uint8_t *)(&skb->data[2]);896hw_cfg_cb.lmp_subversion = le16_to_cpu(*(uint16_t *)(&skb->data[7]));897} else {898RS_ERR("READ_RTK_ROM_VERISION return status error!");899/* Need to do more */900}901skb_free(rtk_h5.host_last_cmd);902rtk_h5.host_last_cmd = NULL;903break;904case HCI_VENDOR_READ_CHIP_TYPE:905gchip_type_cmd_state = event_received;906status = skb->data[0];907RS_DBG("Read RTK CHIP TYPE with Status:%x", status);908if (0 == status) {909hw_cfg_cb.chip_type = *(uint8_t *)(&skb->data[1]);910} else {911RS_ERR("READ_RTK_CHIP_TYPE return status error!");912}913skb_free(rtk_h5.host_last_cmd);914rtk_h5.host_last_cmd = NULL;915break;916case HCI_VENDOR_READ_RTK_ROM_VERISION:917gRom_version_cmd_state = event_received;918status = skb->data[0];919RS_DBG("Read RTK rom version with Status:%x", status);920if (0 == status)921gEVersion = skb->data[1];922else if (1 == status)923gEVersion = 0;924else {925gEVersion = 0;926RS_ERR("READ_RTK_ROM_VERISION return status error!");927/* Need to do more */928}929skb_free(rtk_h5.host_last_cmd);930rtk_h5.host_last_cmd = NULL;931break;932}933}934935/**936* Check if it's a hci frame, if it is, complete it with response or parse the cmd complete event937*938* @param skb socket buffer939*940*/941static void hci_recv_frame(struct sk_buff *skb)942{943char h5sync[2] = {0x01, 0x7E},944h5syncresp[2] = {0x02, 0x7D},945h5_sync_resp_pkt[0x8] = {0xc0, 0x00, 0x2F, 0x00, 0xD0, 0x02, 0x7D, 0xc0},946h5_conf_resp_pkt_to_Ctrl[0x8] = {0xc0, 0x00, 0x2F, 0x00, 0xD0, 0x04, 0x7B, 0xc0},947h5conf[3] = {0x03, 0xFC, 0x10},948h5confresp[3] = {0x04, 0x7B, 0x10},949cmd_complete_evt_code = 0xe;950951if (rtk_h5.link_estab_state == H5_SYNC) { /* sync */952if (!memcmp(skb->data, h5sync, 2)) {953RS_DBG("Get Sync Pkt\n");954write(serial_fd, &h5_sync_resp_pkt, 0x8);955} else if (!memcmp(skb->data, h5syncresp, 2)) {956RS_DBG("Get Sync Resp Pkt\n");957rtk_h5.link_estab_state = H5_CONFIG;958}959skb_free(skb);960} else if (rtk_h5.link_estab_state == H5_CONFIG) { /* config */961if (!memcmp(skb->data, h5sync, 0x2)) {962write(serial_fd, &h5_sync_resp_pkt, 0x8);963RS_DBG("Get SYNC pkt-active mode\n");964} else if (!memcmp(skb->data, h5conf, 0x2)) {965write(serial_fd, &h5_conf_resp_pkt_to_Ctrl, 0x8);966RS_DBG("Get CONFG pkt-active mode\n");967} else if (!memcmp(skb->data, h5confresp, 0x2)) {968RS_DBG("Get CONFG resp pkt-active mode\n");969rtk_h5.link_estab_state = H5_INIT;//H5_PATCH;970//rtk_send_pure_ack_down(serial_fd);971} else {972RS_DBG("H5_CONFIG receive event\n");973rtk_send_pure_ack_down(serial_fd);974}975skb_free(skb);976} else if (rtk_h5.link_estab_state == H5_INIT) {977if (skb->data[0] == cmd_complete_evt_code) {978hci_event_cmd_complete(skb);979}980981rtk_send_pure_ack_down(serial_fd);982usleep(10000);983rtk_send_pure_ack_down(serial_fd);984usleep(10000);985rtk_send_pure_ack_down(serial_fd);986skb_free(skb);987} else if (rtk_h5.link_estab_state == H5_PATCH) { /* patch */988rtk_patch.nRxIndex = skb->data[6];989if (rtk_patch.nRxIndex & 0x80)990rtk_patch.nRxIndex &= ~0x80;991992RS_DBG("rtk_patch.nRxIndex %d\n", rtk_patch.nRxIndex);993if (rtk_patch.nRxIndex == rtk_patch.nTotal)994rtk_h5.link_estab_state = H5_ACTIVE;995skb_free(skb);996} else {997RS_ERR("receive packets in active state");998skb_free(skb);999}1000}10011002/**1003* after rx data is parsed, and we got a rx frame saved in h5->rx_skb,1004* this routinue is called.1005* things todo in this function:1006* 1. check if it's a hci frame, if it is, complete it with response or ack1007* 2. see the ack number, free acked frame in queue1008* 3. reset h5->rx_state, set rx_skb to null.1009*1010* @param h5 realtek h5 struct1011*1012*/1013static void h5_complete_rx_pkt(struct rtk_h5_struct *h5)1014{1015int pass_up = 1;1016uint16_t *valuep, value_t;1017H5_PKT_HEADER *h5_hdr = NULL;1018/* 1 is offset of uint16_t in H5_PKT_HEADER */1019valuep = (uint16_t *)(h5->rx_skb->data+1);1020value_t = le16_to_cpu(*valuep);1021*valuep = value_t;1022h5_hdr = (H5_PKT_HEADER *)(h5->rx_skb->data);1023if (h5_hdr->ReliablePkt) {1024RS_DBG("Received reliable seqno %u from card", h5->rxseq_txack);1025h5->rxseq_txack = h5_hdr->SeqNumber + 1;1026h5->rxseq_txack %= 8;1027h5->is_txack_req = 1;1028/* send down an empty ack if needed. */1029}10301031h5->rxack = h5_hdr->AckNumber;10321033switch (h5_hdr->PktType) {1034case HCI_ACLDATA_PKT:1035case HCI_EVENT_PKT:1036case HCI_SCODATA_PKT:1037case HCI_COMMAND_PKT:1038case H5_LINK_CTL_PKT:1039pass_up = 1;1040break;1041default:1042pass_up = 0;1043}10441045h5_remove_acked_pkt(h5);10461047/* decide if we need to pass up. */1048if (pass_up) {1049/* remove h5 header and send packet to hci */1050skb_pull(h5->rx_skb, sizeof(H5_PKT_HEADER));1051hci_recv_frame(h5->rx_skb);1052/* should skb be freed here? */1053} else {1054/* free skb buffer */1055skb_free(h5->rx_skb);1056}10571058h5->rx_state = H5_W4_PKT_DELIMITER;1059h5->rx_skb = NULL;1060}10611062/**1063* Parse the receive data in h5 proto.1064*1065* @param h5 realtek h5 struct1066* @param data point to data received before parse1067* @param count num of data1068* @return reserved count1069*/1070static int h5_recv(struct rtk_h5_struct *h5, void *data, int count)1071{1072char *ptr;1073ptr = (char *)data;10741075while (count) {1076if (h5->rx_count) {1077if (*ptr == 0xc0) {1078RS_ERR("short h5 packet");1079skb_free(h5->rx_skb);1080h5->rx_state = H5_W4_PKT_START;1081h5->rx_count = 0;1082} else {1083h5_unslip_one_byte(h5, *ptr);1084}1085ptr++;1086count--;1087continue;1088}10891090switch (h5->rx_state) {1091case H5_W4_HDR:1092/* check header checksum. see Core Spec V4 "3-wire uart" page 67 */1093if ((0xff & (uint8_t) ~(h5->rx_skb->data[0] + h5->rx_skb->data[1] +1094h5->rx_skb->data[2])) != h5->rx_skb->data[3]) {1095RS_ERR("h5 hdr checksum error!!!");1096skb_free(h5->rx_skb);1097h5->rx_state = H5_W4_PKT_DELIMITER;1098h5->rx_count = 0;1099continue;1100}11011102if (h5->rx_skb->data[0] & 0x80 /* reliable pkt */1103&& (h5->rx_skb->data[0] & 0x07) != h5->rxseq_txack) {1104RS_ERR("Out-of-order packet arrived, got(%d)expected(%u)",1105h5->rx_skb->data[0] & 0x07, h5->rxseq_txack);1106h5->is_txack_req = 1;1107skb_free(h5->rx_skb);1108h5->rx_state = H5_W4_PKT_DELIMITER;1109h5->rx_count = 0;11101111if (rtk_patch.nTxIndex == rtk_patch.nTotal) {1112/* depend on weather remote will reset ack numb or not!!!!!!!!!!!!!!!special */1113rtk_h5.rxseq_txack = h5->rx_skb->data[0] & 0x07;1114}1115continue;1116}11171118h5->rx_state = H5_W4_DATA;11191120/* payload length: May be 0 */1121h5->rx_count = (h5->rx_skb->data[1] >> 4) + (h5->rx_skb->data[2] << 4);1122continue;1123case H5_W4_DATA:1124if (h5->rx_skb->data[0] & 0x40) { /* pkt with crc */1125h5->rx_state = H5_W4_CRC;1126h5->rx_count = 2;1127} else {1128h5_complete_rx_pkt(h5); /* Send ACK */1129}1130continue;11311132case H5_W4_CRC:1133if (bit_rev16(h5->message_crc) != h5_get_crc(h5)) {1134RS_ERR("Checksum failed, computed(%04x)received(%04x)",1135bit_rev16(h5->message_crc), h5_get_crc(h5));1136skb_free(h5->rx_skb);1137h5->rx_state = H5_W4_PKT_DELIMITER;1138h5->rx_count = 0;1139continue;1140}1141skb_trim(h5->rx_skb, h5->rx_skb->data_len - 2);1142h5_complete_rx_pkt(h5);1143continue;11441145case H5_W4_PKT_DELIMITER:1146switch (*ptr) {1147case 0xc0:1148h5->rx_state = H5_W4_PKT_START;1149break;1150default:1151break;1152}1153ptr++;1154count--;1155break;11561157case H5_W4_PKT_START:1158switch (*ptr) {1159case 0xc0:1160ptr++;1161count--;1162break;1163default:1164h5->rx_state = H5_W4_HDR;1165h5->rx_count = 4;1166h5->rx_esc_state = H5_ESCSTATE_NOESC;1167h5->message_crc = 0xffff;11681169/* Do not increment ptr or decrement count1170* Allocate packet. Max len of a H5 pkt=1171* 0xFFF (payload) +4 (header) +2 (crc) */1172h5->rx_skb = skb_alloc(0x1005);1173if (!h5->rx_skb) {1174h5->rx_state = H5_W4_PKT_DELIMITER;1175h5->rx_count = 0;1176return 0;1177}1178break;1179}1180break;1181}1182}1183return count;1184}11851186/**1187* Read data to buf from uart.1188*1189* @param fd uart file descriptor1190* @param buf point to the addr where read data stored1191* @param count num of data want to read1192* @return num of data successfully read1193*/1194static int read_check(int fd, void *buf, int count)1195{1196int res;1197do {1198res = read(fd, buf, count);1199if (res != -1) {1200buf = (uint8_t *)buf + res;1201count -= res;1202return res;1203}1204} while (count && (errno == 0 || errno == EINTR));1205return res;1206}12071208/**1209* Retry to sync when timeout in h5 proto, max retry times is 10.1210*1211* @warning Each time to retry, the time for timeout will be set as 1s.1212*1213* @param sig signaction for timeout1214*1215*/1216static void h5_tshy_sig_alarm(int sig)1217{1218uint8_t h5sync[2] = {0x01, 0x7E};1219static int retries;1220struct itimerval value;12211222if (retries < h5_max_retries) {1223retries++;1224struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, h5sync, sizeof(h5sync), H5_LINK_CTL_PKT);1225int len = write(serial_fd, nskb->data, nskb->data_len);1226RS_DBG("3-wire sync pattern resend : %d, len: %d\n", retries, len);1227skb_free(nskb);12281229/* retry per 250ms */1230value.it_value.tv_sec = 0;1231value.it_value.tv_usec = 250000;1232value.it_interval.tv_sec = 0;1233value.it_interval.tv_usec = 250000;1234setitimer(ITIMER_REAL, &value, NULL);12351236return;1237}12381239tcflush(serial_fd, TCIOFLUSH);1240RS_ERR("H5 sync timed out\n");1241exit(1);1242}12431244/**1245* Retry to config when timeout in h5 proto, max retry times is 10.1246*1247* @warning Each time to retry, the time for timeout will be set as 1s.1248*1249* @param sig signaction for timeout1250*1251*/1252static void h5_tconf_sig_alarm(int sig)1253{1254uint8_t h5conf[3] = {0x03, 0xFC, 0x14};1255static int retries;1256struct itimerval value;12571258if (retries < h5_max_retries) {1259retries++;1260struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, h5conf, 3, H5_LINK_CTL_PKT);1261int len = write(serial_fd, nskb->data, nskb->data_len);1262RS_DBG("3-wire config pattern resend : %d , len: %d", retries, len);1263skb_free(nskb);12641265/* retry per 250ms */1266value.it_value.tv_sec = 0;1267value.it_value.tv_usec = 250000;1268value.it_interval.tv_sec = 0;1269value.it_interval.tv_usec = 250000;1270setitimer(ITIMER_REAL, &value, NULL);12711272return;1273}12741275tcflush(serial_fd, TCIOFLUSH);1276RS_ERR("H5 config timed out\n");1277exit(1);1278}12791280/**1281* Retry to init when timeout in h5 proto, max retry times is 10.1282*1283* @warning Each time to retry, the time for timeout will be set as 1s.1284*1285* @param sig signaction for timeout1286*1287*/1288static void h5_tinit_sig_alarm(int sig)1289{1290static int retries;1291if (retries < h5_max_retries) {1292retries++;1293if (rtk_h5.host_last_cmd) {1294int len = write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);1295RS_DBG("3-wire change baudrate re send:%d, len:%d", retries, len);1296alarm(1);1297return;1298} else {1299RS_DBG("3-wire init timeout without last command stored\n");1300}1301}13021303tcflush(serial_fd, TCIOFLUSH);1304RS_ERR("H5 init process timed out");1305exit(1);1306}13071308/**1309* Retry to download patch when timeout in h5 proto, max retry times is 10.1310*1311* @warning Each time to retry, the time for timeout will be set as 3s.1312*1313* @param sig signaction for timeout1314*1315*/1316static void h5_tpatch_sig_alarm(int sig)1317{1318static int retries;1319if (retries < h5_max_retries) {1320RS_DBG("patch timerout, retry:\n");1321if (rtk_h5.host_last_cmd) {1322write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);1323RS_DBG("3-wire download patch re send:%d", retries);1324}1325retries++;1326alarm(3);1327return;1328}1329RS_ERR("H5 patch timed out\n");1330exit(1);1331}13321333/**1334* Download patch using hci. For h5 proto, not recv reply for 2s will timeout.1335* Call h5_tpatch_sig_alarm for retry.1336*1337* @param dd uart file descriptor1338* @param index current index1339* @param data point to the config file1340* @param len current buf length1341* @return #0 on success1342*1343*/1344static int hci_download_patch(int dd, int index, uint8_t *data, int len, struct termios *ti)1345{1346uint8_t hcipatch[256] = {0x20, 0xfc, 00};1347char bytes[READ_DATA_SIZE];1348int retlen;1349struct sigaction sa;13501351sa.sa_handler = h5_tpatch_sig_alarm;1352sigaction(SIGALRM, &sa, NULL);1353alarm(2);13541355download_vendor_patch_cp cp;1356memset(&cp, 0, sizeof(cp));1357cp.index = index;1358if (data != NULL) {1359memcpy(cp.data, data, len);1360}13611362int nValue = rtk_patch.nTotal|0x80;1363if (index == nValue) {1364rtk_patch.nTxIndex = rtk_patch.nTotal;1365} else {1366rtk_patch.nTxIndex = index;1367}1368hcipatch[2] = len+1;1369memcpy(hcipatch+3, &cp, len+1);13701371struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, hcipatch, len+4, HCI_COMMAND_PKT); /* data: len + head: 4 */13721373if (rtk_h5.host_last_cmd) {1374skb_free(rtk_h5.host_last_cmd);1375rtk_h5.host_last_cmd = NULL;1376}13771378rtk_h5.host_last_cmd = nskb;13791380len = write(dd, nskb->data, nskb->data_len);1381RS_DBG("hci_download_patch nTxIndex:%d nRxIndex: %d\n", rtk_patch.nTxIndex, rtk_patch.nRxIndex);13821383if (index & 0x80) {1384RS_DBG("Hw Flow Control enable after last command sent before last event recv ! ");1385if (tcsetattr(dd, TCSADRAIN, ti) < 0) {1386RS_ERR("Can't set port settings");1387return -1;1388}1389}13901391while (rtk_patch.nRxIndex != rtk_patch.nTxIndex) { /* receive data and wait last pkt */1392retlen = read_check(dd, &bytes, READ_DATA_SIZE);1393if (retlen == -1) {1394perror("read fail");1395return -1;1396}1397h5_recv(&rtk_h5, &bytes, retlen);1398}13991400alarm(0);1401return 0;1402}14031404/**1405* Download h4 patch1406*1407* @param dd uart file descriptor1408* @param index current index1409* @param data point to the config file1410* @param len current buf length1411* @return ret_index1412*1413*/1414static int hci_download_patch_h4(int dd, int index, uint8_t *data, int len)1415{1416char bytes[257] = {0};1417char buf[257] = {0x01, 0x20, 0xfc, 00};14181419RS_DBG("dd:%d, index:%d, len:%d", dd, index, len);1420if (NULL != data) {1421memcpy(&buf[5], data, len);1422}14231424int cur_index = index;1425int ret_Index = -1;14261427/* Set data struct. */1428buf[3] = len + 1; /* add index */1429buf[4] = cur_index;1430size_t total_len = len + 5;14311432/* write */1433uint16_t w_len;1434w_len = write(dd, buf, total_len);1435RS_DBG("h4 write success with len: %d.\n", w_len);14361437uint16_t res;1438res = read(dd, bytes, 8);14391440if (DBG_ON) {1441RS_DBG("h4 read success with len: %d.\n", res);1442int i = 0;1443for (i = 0; i < 8; i++) {1444fprintf(stderr, "byte[%d] = 0x%x\n", i, bytes[i]);1445}1446}14471448uint8_t rstatus;1449if ((0x04 == bytes[0]) && (0x20 == bytes[4]) && (0xfc == bytes[5])) {1450ret_Index = bytes[7];1451rstatus = bytes[6];1452RS_DBG("---->ret_Index:%d, ----->rstatus:%d\n", ret_Index, rstatus);1453if (0x00 != rstatus) {1454RS_ERR("---->read event status is wrong.\n");1455return -1;1456}1457} else {1458RS_ERR("==========>Didn't read curret data.\n");1459return -1;1460}14611462return ret_Index;1463}14641465/**1466* Realtek change speed with h4 proto. Using vendor specified command packet to achieve this.1467*1468* @warning before write, need to wait 1s for device up1469*1470* @param fd uart file descriptor1471* @param baudrate the speed want to change1472* @return #0 on success1473*/1474static int rtk_vendor_change_speed_h4(int fd, uint32_t baudrate)1475{1476char bytes[257];1477uint8_t cmd[8] = {0};14781479cmd[0] = 1; /* cmd */1480cmd[1] = 0x17; /* ocf */1481cmd[2] = 0xfc; /* ogf, vendor specified */14821483cmd[3] = 4; /* length */1484#ifdef BAUDRATE_4BYTES1485memcpy((uint16_t *)&cmd[4], &baudrate, 4);1486#else1487memcpy((uint16_t *)&cmd[4], &baudrate, 2);14881489cmd[6] = 0;1490cmd[7] = 0;1491#endif14921493/* wait for a while for device to up, just h4 need it */1494sleep(1);14951496if (write(fd, cmd, 8) != 8) {1497RS_ERR("H4 change uart speed error when writing vendor command");1498return -1;1499}1500RS_DBG("H4 Change uart Baudrate after write ");1501int res;1502res = read(fd, bytes, sizeof(bytes));15031504if (DBG_ON) {1505RS_DBG("Realtek Receving H4 change uart speed event:%x", res);1506RS_DUMP(bytes, res);1507}1508if ((0x04 == bytes[0]) && (0x17 == bytes[4]) && (0xfc == bytes[5])) {1509RS_DBG("H4 change uart speed success, receving status:%x", bytes[6]);1510if (bytes[6] == 0)1511return 0;1512}1513return -1;1514}15151516/**1517* Parse realtek Bluetooth config file.1518* The config file if begin with vendor magic: RTK_VENDOR_CONFIG_MAGIC(8723ab55)1519* bt_addr is followed by 0x3c offset, it will be changed by bt_addr param1520* proto, baudrate and flow control is followed by 0xc offset,1521*1522* @param config_buf point to config file content1523* @param filelen length of config file1524* @param bt_addr where bt addr is stored1525* @return baudrate in config file1526*1527*/15281529static uint32_t rtk_parse_config_file(uint8_t *config_buf, size_t filelen, char bt_addr[6])1530{1531struct rtk_bt_vendor_config *config = (struct rtk_bt_vendor_config *) config_buf;1532uint16_t config_len = le16_to_cpu(config->data_len), temp = 0;1533struct rtk_bt_vendor_config_entry *entry = config->entry;15341535uint16_t i;1536uint32_t baudrate = 0;15371538if (le32_to_cpu(config->signature) != RTK_VENDOR_CONFIG_MAGIC) {1539RS_ERR("config signature magic number(%x) is not set to RTK_VENDOR_CONFIG_MAGIC", (int)config->signature);1540return 0;1541}15421543if (config_len != filelen - sizeof(struct rtk_bt_vendor_config)) {1544RS_ERR("config len(%x) is not right(%x)", config_len, filelen-sizeof(struct rtk_bt_vendor_config));1545return 0;1546}15471548for (i = 0; i < config_len;) {1549switch (le16_to_cpu(entry->offset)) {1550case 0x3c:1551{1552int j = 0;1553for (j = 0; j < entry->entry_len; j++)1554entry->entry_data[j] = bt_addr[entry->entry_len - 1 - j];1555}1556break;1557case 0xc:1558#ifdef BAUDRATE_4BYTES1559baudrate = *(uint32_t *)entry->entry_data;1560#else1561baudrate = *(uint16_t *)entry->entry_data;1562#endif1563gHwFlowControlEnable = 0;1564if (entry->entry_len >= 12) { //0ffset 0x18 - 0xc1565gHwFlowControlEnable = (entry->entry_data[12] & 0x4) ? 1:0; //0x18 byte bit21566}1567RS_DBG("config baud rate to :%x, hwflowcontrol:%x, %x", (int)baudrate, entry->entry_data[12], gHwFlowControlEnable);1568break;1569default:1570RS_DBG("config offset(%x),length(%x)", entry->offset, entry->entry_len);1571break;1572}1573temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);1574i += temp;1575entry = (struct rtk_bt_vendor_config_entry *)((uint8_t *)entry + temp);1576}15771578return baudrate;1579}15801581/**1582* get random realtek Bluetooth addr.1583*1584* @param bt_addr where bt addr is stored1585*1586*/1587static void rtk_get_ram_addr(char bt_addr[0])1588{1589srand(time(NULL)+getpid()+getpid()*987654+rand());15901591uint32_t addr = rand();1592memcpy(bt_addr, &addr, sizeof(uint8_t));1593}15941595/**1596* Write the random bt addr to the file /data/misc/bluetooth/btmac.txt.1597*1598* @param bt_addr where bt addr is stored1599*1600*/1601static void rtk_write_btmac2file(char bt_addr[6])1602{1603int fd;1604mkdir(BT_ADDR_DIR, 0777);1605fd = open(BT_ADDR_FILE, O_CREAT|O_RDWR|O_TRUNC, 0666);16061607if (fd > 0) {1608chmod(BT_ADDR_FILE, 0666);1609char addr[18] = {0};1610addr[17] = '\0';1611sprintf(addr, "%2x:%2x:%2x:%2x:%2x:%2x", bt_addr[0], bt_addr[1], bt_addr[2], bt_addr[3], bt_addr[4], bt_addr[5]);1612write(fd, addr, strlen(addr));1613close(fd);1614} else {1615RS_ERR("open file error:%s\n", BT_ADDR_FILE);1616}1617}16181619/**1620* Get realtek Bluetooth config file. The bt addr arg is stored in /data/btmac.txt, if there is not this file,1621* change to /data/misc/bluetooth/btmac.txt. If both of them are not found, using1622* random bt addr.1623*1624* The config file is rtk8723_bt_config whose bt addr will be changed by the one read previous1625*1626* @param config_buf point to the content of realtek Bluetooth config file1627* @param config_baud_rate the baudrate set in the config file1628* @return file_len the length of config file1629*/1630static int rtk_get_bt_config(uint8_t **config_buf, uint32_t *config_baud_rate, patch_info *info)1631{1632char bt_config_file_name[PATH_MAX] = {0};1633char bt_addr[6] = {0x00, 0xe0, 0x4c, 0x88, 0x88, 0x88};1634struct stat st;1635size_t filelen;1636int fd;1637FILE *file = NULL;1638int i = 0;16391640sprintf(bt_config_file_name, "%s/%s", BT_CONFIG_DIRECTORY, "btmac.txt");1641RS_DBG("BT mac addr file: %s", bt_config_file_name);1642if (stat(bt_config_file_name, &st) < 0) {1643RS_ERR("can't access bt bt_mac_addr file:%s, try use another path", bt_config_file_name);1644sprintf(bt_config_file_name, BT_ADDR_FILE);1645if (stat(bt_config_file_name, &st) < 0) {1646RS_ERR("can't access bt bt_mac_addr file:%s, try use ramdom BT Addr", bt_config_file_name);16471648for (i = 0; i < 6; i++)1649rtk_get_ram_addr(&bt_addr[i]);1650rtk_write_btmac2file(bt_addr);1651goto GET_CONFIG;1652}1653}16541655filelen = st.st_size;1656file = fopen(bt_config_file_name, "rb");1657if (file == NULL) {1658RS_ERR("Can't open bt btaddr file, just use preset BT Addr");1659} else {1660fscanf(file, "%2x:%2x:%2x:%2x:%2x:%2x", (int *)&bt_addr[0], (uint32_t *)&bt_addr[1], (uint32_t *)&bt_addr[2], (uint32_t *)&bt_addr[3], (uint32_t *)&bt_addr[4], (uint32_t *)&bt_addr[5]);1661/* do not set bt_add[0] to zero */1662/* reserve LAP addr from 0x9e8b00 to 0x9e8b3f, change to 0x008b */1663if (0x9e == bt_addr[3] && 0x8b == bt_addr[4] && (bt_addr[5] <= 0x3f)) {1664/* get random value */1665bt_addr[3] = 0x00;1666}1667RS_DBG("BT MAC IS : %02X:%02X:%02X:%02X:%02X:%02X", bt_addr[0], bt_addr[1], bt_addr[2], bt_addr[3], bt_addr[4], bt_addr[5]);1668}16691670GET_CONFIG:1671if (info != NULL) {1672sprintf(bt_config_file_name, "%s/%s", BT_CONFIG_DIRECTORY, info->config_name);1673} else {1674sprintf(bt_config_file_name, "%s/%s", BT_CONFIG_DIRECTORY, "rtlbt_config");1675}1676RS_DBG("Final bt config file: %s", bt_config_file_name);16771678if (stat(bt_config_file_name, &st) < 0) {1679RS_ERR("Can't access firmware, errno:%d", errno);1680return -1;1681}16821683filelen = st.st_size;16841685fd = open(bt_config_file_name, O_RDONLY);1686if (fd < 0) {1687perror("Can't open bt config file");1688return -1;1689}16901691*config_buf = malloc(filelen);1692if (*config_buf == NULL) {1693RS_DBG("malloc buffer for config file fail(%x)\n", filelen);1694close(fd);1695return -1;1696}16971698/* we may need to parse this config file. */1699/* for easy debug, only get need data. */1700if (read(fd, *config_buf, filelen) < (ssize_t)filelen) {1701perror("Can't load bt config file");1702free(*config_buf);1703*config_buf = NULL;1704close(fd);1705return -1;1706}17071708*config_baud_rate = rtk_parse_config_file(*config_buf, filelen, bt_addr);1709RS_DBG("Get config baud rate(4 bytes) from config file:%x", (int)*config_baud_rate);17101711close(fd);1712return filelen;1713}17141715/**1716* Realtek change speed with h5 proto. Using vendor specified command packet to achieve this.1717*1718* @warning it will waiting 2s for reply.1719*1720* @param fd uart file descriptor1721* @param baudrate the speed want to change1722*1723*/1724static int rtk_vendor_change_speed_h5(int fd, uint32_t baudrate)1725{1726struct sk_buff *cmd_change_bdrate = NULL;1727uint8_t cmd[7] = {0};1728int retlen;1729char bytes[READ_DATA_SIZE];1730struct sigaction sa;17311732sa.sa_handler = h5_tinit_sig_alarm;1733sigaction(SIGALRM, &sa, NULL);17341735cmd[0] = 0x17; /* ocf */1736cmd[1] = 0xfc; /* ogf, vendor specified */17371738cmd[2] = 4; /* length */1739#ifdef BAUDRATE_4BYTES1740memcpy((uint16_t *)&cmd[3], &baudrate, 4);1741#else1742memcpy((uint16_t *)&cmd[3], &baudrate, 2);1743cmd[5] = 0;1744cmd[6] = 0;1745#endif17461747if (DBG_ON) {1748RS_DUMP(cmd, 7);1749RS_DBG("change speed command ready baudrate=%d n", baudrate);1750}1751cmd_change_bdrate = h5_prepare_pkt(&rtk_h5, cmd, 7, HCI_COMMAND_PKT);1752if (!cmd_change_bdrate) {1753RS_ERR("Prepare command packet for change speed fail");1754return -1;1755}17561757rtk_h5.host_last_cmd = cmd_change_bdrate;1758alarm(1);1759write(fd, cmd_change_bdrate->data, cmd_change_bdrate->data_len);17601761while (rtk_h5.link_estab_state == H5_INIT) {1762retlen = read_check(fd, &bytes, READ_DATA_SIZE);1763if (retlen == -1) {1764perror("read fail");1765return -1;1766}17671768/* add pure ack check */1769h5_recv(&rtk_h5, &bytes, retlen);1770}17711772alarm(0);1773return 0;1774}17751776/**1777* Init realtek Bluetooth h5 proto. h5 proto is added by realtek in the right kernel.1778* Generally there are two steps: h5 sync and h5 config1779*1780* @param fd uart file descriptor1781* @param ti termios struct1782*1783*/1784static int rtk_init_h5(int fd, struct termios *ti)1785{1786char bytes[READ_DATA_SIZE];1787struct sigaction sa;1788int retlen;1789struct itimerval value;17901791/* set even parity here */1792ti->c_cflag |= PARENB;1793ti->c_cflag &= ~(PARODD);1794if (tcsetattr(fd, TCSANOW, ti) < 0) {1795RS_ERR("Can't set port settings");1796return -1;1797}17981799alarm(0);1800serial_fd = fd;1801memset(&sa, 0, sizeof(sa));1802sa.sa_flags = SA_NOCLDSTOP;1803sa.sa_handler = h5_tshy_sig_alarm;1804sigaction(SIGALRM, &sa, NULL);18051806/* h5 sync */1807h5_tshy_sig_alarm(0);1808memset(&rtk_h5, 0, sizeof(rtk_h5));1809rtk_h5.link_estab_state = H5_SYNC;1810while (rtk_h5.link_estab_state == H5_SYNC) {1811retlen = read_check(fd, &bytes, READ_DATA_SIZE);1812if (retlen == -1) {1813RS_ERR("H5 Read Sync Response Failed");1814/* retry per 250ms */1815value.it_value.tv_sec = 0;1816value.it_value.tv_usec = 0;1817value.it_interval.tv_sec = 0;1818value.it_interval.tv_usec = 0;1819setitimer(ITIMER_REAL, &value, NULL);1820return -1;1821}1822h5_recv(&rtk_h5, &bytes, retlen);1823}18241825/* retry per 250ms */1826value.it_value.tv_sec = 0;1827value.it_value.tv_usec = 0;1828value.it_interval.tv_sec = 0;1829value.it_interval.tv_usec = 0;1830setitimer(ITIMER_REAL, &value, NULL);18311832/* h5 config */1833sa.sa_handler = h5_tconf_sig_alarm;1834sigaction(SIGALRM, &sa, NULL);1835h5_tconf_sig_alarm(0);1836while (rtk_h5.link_estab_state == H5_CONFIG) {1837retlen = read_check(fd, &bytes, READ_DATA_SIZE);1838if (retlen == -1) {1839RS_ERR("H5 Read Config Response Failed");1840/* retry per 250ms */1841value.it_value.tv_sec = 0;1842value.it_value.tv_usec = 0;1843value.it_interval.tv_sec = 0;1844value.it_interval.tv_usec = 0;1845setitimer(ITIMER_REAL, &value, NULL);1846return -1;1847}1848h5_recv(&rtk_h5, &bytes, retlen);1849}1850/* retry per 250ms */1851value.it_value.tv_sec = 0;1852value.it_value.tv_usec = 0;1853value.it_interval.tv_sec = 0;1854value.it_interval.tv_usec = 0;1855setitimer(ITIMER_REAL, &value, NULL);18561857rtk_send_pure_ack_down(fd);1858RS_DBG("H5 init finished\n");1859return 0;1860}18611862/**1863* Download realtek firmware and config file from uart with the proto.1864* Parse the content to serval packets follow the proto and then write the packets from uart1865*1866* @param fd uart file descriptor1867* @param buf addr where stor the content of firmware and config file1868* @param filesize length of buf1869* @param is_sent_changerate if baudrate need to be changed1870* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE1871*1872*/1873static void rtk_download_fw_config(int fd, uint8_t *buf, size_t filesize, int is_sent_changerate, int proto, struct termios *ti)1874{1875uint8_t iCurIndex = 0;1876uint8_t iCurLen = 0;1877uint8_t iEndIndex = 0;1878uint8_t iLastPacketLen = 0;1879uint8_t iAdditionPkt = 0;1880uint8_t iTotalIndex = 0;1881uint8_t iCmdSentNum = 0; /* the number of CMDs which have been sent */1882uint8_t *bufpatch;18831884iEndIndex = (uint8_t)((filesize-1)/PATCH_DATA_FIELD_MAX_SIZE);1885iLastPacketLen = (filesize)%PATCH_DATA_FIELD_MAX_SIZE;18861887if (is_sent_changerate)1888iCmdSentNum++;1889if (gRom_version_cmd_state >= cmd_has_sent)1890iCmdSentNum++;1891if (ghci_version_cmd_state >= cmd_has_sent)1892iCmdSentNum++;1893if (gchip_type_cmd_state >= cmd_has_sent)1894iCmdSentNum++;18951896iAdditionPkt = (iEndIndex+1+iCmdSentNum)%8?(8-(iEndIndex+1+iCmdSentNum)%8):0;1897iTotalIndex = iAdditionPkt + iEndIndex;1898rtk_patch.nTotal = iTotalIndex; /* init TotalIndex */18991900RS_DBG("iEndIndex:%d iLastPacketLen:%d iAdditionpkt:%d\n", iEndIndex, iLastPacketLen, iAdditionPkt);19011902if (iLastPacketLen == 0)1903iLastPacketLen = PATCH_DATA_FIELD_MAX_SIZE;19041905bufpatch = buf;19061907int i;1908for (i = 0; i <= iTotalIndex; i++) {1909if (iCurIndex < iEndIndex) {1910iCurIndex = iCurIndex&0x7F;1911iCurLen = PATCH_DATA_FIELD_MAX_SIZE;1912} else if (iCurIndex == iEndIndex) { /* send last data packet */1913if (iCurIndex == iTotalIndex)1914iCurIndex = iCurIndex | 0x80;1915else1916iCurIndex = iCurIndex&0x7F;1917iCurLen = iLastPacketLen;1918} else if (iCurIndex < iTotalIndex) {1919iCurIndex = iCurIndex&0x7F;1920bufpatch = NULL;1921iCurLen = 0;1922} else { /* send end packet */1923bufpatch = NULL;1924iCurLen = 0;1925iCurIndex = iCurIndex|0x80;1926}19271928if (iCurIndex & 0x80)1929RS_DBG("Send FW last command");19301931if (proto == HCI_UART_H4) {1932iCurIndex = hci_download_patch_h4(fd, iCurIndex, bufpatch, iCurLen);1933if ((iCurIndex != i) && (i != rtk_patch.nTotal)) {1934/* check index but ignore last pkt */1935RS_DBG("index mismatch i:%d iCurIndex:%d, patch fail\n", i, iCurIndex);1936return;1937}1938} else if (proto == HCI_UART_3WIRE)1939hci_download_patch(fd, iCurIndex, bufpatch, iCurLen, ti);19401941if (iCurIndex < iEndIndex) {1942bufpatch += PATCH_DATA_FIELD_MAX_SIZE;1943}1944iCurIndex++;1945}19461947/* set last ack packet down */1948if (proto == HCI_UART_3WIRE) {1949rtk_send_pure_ack_down(fd);1950}1951}19521953/**1954* Get realtek Bluetooth firmaware file. The content will be saved in *fw_buf which is malloc here.1955* The length malloc here will be lager than length of firmware file if there is a config file.1956* The content of config file will copy to the tail of *fw_buf in rtk_config.1957*1958* @param fw_buf point to the addr where stored the content of firmware.1959* @param addi_len length of config file.1960* @return length of *fw_buf.1961*1962*/1963static int rtk_get_bt_firmware(uint8_t **fw_buf, size_t addi_len, patch_info *info)1964{1965char filename[PATH_MAX] = {0};1966struct stat st;1967int fd = -1;1968size_t fwsize, buf_size;19691970if (info != NULL) {1971sprintf(filename, "%s/%s", FIRMWARE_DIRECTORY, info->patch_name);1972} else {1973sprintf(filename, "%s/%s", FIRMWARE_DIRECTORY, "rtlbt_fw");1974}19751976RS_DBG("Final bt firmware file: %s", filename);19771978if (stat(filename, &st) < 0) {1979RS_ERR("Can't access firmware, errno:%d", errno);1980return -1;1981}19821983fwsize = st.st_size;1984buf_size = fwsize + addi_len;19851986fd = open(filename, O_RDONLY);1987if (fd < 0) {1988RS_ERR("Can't open firmware, errno:%d", errno);1989return -1;1990}19911992*fw_buf = malloc(buf_size);1993if (!(*fw_buf)) {1994RS_ERR("Can't alloc memory for fw&config, errno:%d", errno);1995close(fd);1996return -1;1997}19981999if (read(fd, *fw_buf, fwsize) < (ssize_t) fwsize) {2000free(*fw_buf);2001*fw_buf = NULL;2002close(fd);2003return -1;2004}2005RS_DBG("Load FW OK");2006close(fd);2007return buf_size;2008}20092010/* These two function(rtk<-->uart speed transfer) need check Host uart speed at first!!!! IMPORTANT2011* add more speed if neccessary */2012typedef struct _baudrate_ex {2013uint32_t rtk_speed;2014int uart_speed;2015} baudrate_ex;20162017#ifdef BAUDRATE_4BYTES2018static baudrate_ex baudrates[] = {2019{0x00006004, 921600},2020{0x05F75004, 921600}, // RTL8723BS2021{0x00004003, 1500000},2022{0x04928002, 1500000}, // RTL8723BS2023{0x00005002, 2000000}, // same as RTL8723AS2024{0x00008001, 3000000},2025{0x00009001, 3000000}, // Lory add new, t169 and t9e use 0x00009001.2026{0x06DD8001, 3000000}, // RTL8723BS, Baudrate: 29200002027{0x036D8001, 3000000}, // RTL8723BS, Baudrate: 29299992028{0x06B58001, 3000000}, // RTL8723BS, Baudrate: 29400002029{0x02B58001, 3000000}, // RTL8723BS, Baudrate: 29450002030{0x02D58001, 3000000}, // RTL8723BS, Baudrate: 29500002031{0x05558001, 3000000}, // RTL8723BS, Baudrate: 29600002032{0x02AA8001, 3000000}, // RTL8723BS, Baudrate: 29699992033{0x052A8001, 3000000}, // RTL8723BS, Baudrate: 29800002034{0x04928001, 3000000}, // RTL8723BS, Baudrate: 29980002035{0x00007001, 3500000},2036{0x052A6001, 3500000}, // RTL8723BS2037{0x00005001, 4000000}, // same as RTL8723AS2038{0x05AD9005, 547000},2039{0x0252C00A, 230400},2040{0x0000701d, 115200},2041{0x0252C002, 115200}, // RTL8723BS2042{0x0252C014, 115200} // RTL8723BS2043};20442045#else2046static baudrate_ex baudrates[] = {2047{0x7001, 3500000},2048{0x6004, 921600},2049{0x4003, 1500000},2050{0x5001, 4000000},2051{0x5002, 2000000},2052{0x8001, 3000000},2053{0x9001, 3000000},2054{0x701d, 115200}2055};20562057#endif205820592060/**2061* Change realtek Bluetooth speed to uart speed. It is matching in the struct baudrates:2062*2063* @code2064* baudrate_ex baudrates[] =2065* {2066* {0x7001, 3500000},2067* {0x6004, 921600},2068* {0x4003, 1500000},2069* {0x5001, 4000000},2070* {0x5002, 2000000},2071* {0x8001, 3000000},2072* {0x701d, 115200}2073* };2074* @endcode2075*2076* If there is no match in baudrates, uart speed will be set as #115200.2077*2078* @param rtk_speed realtek Bluetooth speed2079* @param uart_speed uart speed2080*2081*/2082static void rtk_speed_to_uart_speed(uint32_t rtk_speed, uint32_t *uart_speed)2083{2084*uart_speed = 115200;20852086int i;2087for (i = 0; i < sizeof(baudrates)/sizeof(baudrate_ex); i++) {2088if (baudrates[i].rtk_speed == le32_to_cpu(rtk_speed)) {2089*uart_speed = baudrates[i].uart_speed;2090return;2091}2092}2093return;2094}20952096/**2097* Change uart speed to realtek Bluetooth speed. It is matching in the struct baudrates:2098*2099* @code2100* baudrate_ex baudrates[] =2101* {2102* {0x7001, 3500000},2103* {0x6004, 921600},2104* {0x4003, 1500000},2105* {0x5001, 4000000},2106* {0x5002, 2000000},2107* {0x8001, 3000000},2108* {0x701d, 115200}2109* };2110* @endcode2111*2112* If there is no match in baudrates, realtek Bluetooth speed will be set as #0x701D.2113*2114* @param uart_speed uart speed2115* @param rtk_speed realtek Bluetooth speed2116*2117*/2118static inline void uart_speed_to_rtk_speed(int uart_speed, uint32_t *rtk_speed)2119{2120*rtk_speed = 0x701D;21212122int i;2123for (i = 0; i < sizeof(baudrates) / sizeof(baudrate_ex); i++) {2124if (baudrates[i].uart_speed == uart_speed) {2125*rtk_speed = baudrates[i].rtk_speed;2126return;2127}2128}21292130return;2131}21322133static void rtk_get_eversion_timeout(int sig)2134{2135static int retries;2136RS_DBG("RTK get HCI_VENDOR_READ_RTK_ROM_VERISION_Command\n");2137if (retries < h5_max_retries) {2138RS_DBG("patch timerout, retry:\n");2139if (rtk_h5.host_last_cmd) {2140write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);2141RS_DBG("3-wire download patch re send:%d", retries);2142}2143retries++;2144alarm(3);2145return;2146}2147tcflush(serial_fd, TCIOFLUSH);2148RS_ERR("rtk get eversion cmd complete event timed out\n");2149exit(1);2150}21512152/**2153* Send vendor cmd to get eversion: 0xfc6d2154* If Rom code does not support this cmd, use default.2155*/2156static void rtk_get_eversion(int dd)2157{2158char bytes[READ_DATA_SIZE];2159int retlen;2160struct sigaction sa;2161/* send HCI_VENDOR_READ_RTK_ROM_VERISION Command */2162uint8_t read_rom_patch_cmd[3] = {0x6d, 0xfc, 0x00};2163struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, read_rom_patch_cmd, 3, HCI_COMMAND_PKT); /* data: len+head: 4 */21642165if (rtk_h5.host_last_cmd) {2166skb_free(rtk_h5.host_last_cmd);2167rtk_h5.host_last_cmd = NULL;2168}21692170rtk_h5.host_last_cmd = nskb;21712172write(dd, nskb->data, nskb->data_len);2173gRom_version_cmd_state = cmd_has_sent;2174RS_DBG("RTK send HCI_VENDOR_READ_RTK_ROM_VERISION_Command\n");21752176alarm(0);2177memset(&sa, 0, sizeof(sa));2178sa.sa_flags = SA_NOCLDSTOP;2179sa.sa_handler = rtk_get_eversion_timeout;2180sigaction(SIGALRM, &sa, NULL);21812182alarm(3);2183while (gRom_version_cmd_state != event_received) {2184retlen = read_check(dd, &bytes, READ_DATA_SIZE);2185if (retlen == -1) {2186perror("read fail");2187return;2188}2189h5_recv(&rtk_h5, &bytes, retlen);2190}2191alarm(0);2192return;2193}21942195static void rtk_get_lmp_version_timeout(int sig)2196{2197static int retries;2198RS_DBG("RTK get HCI_VENDOR_READ_RTK_LMP_VERISION_Command\n");2199if (retries < h5_max_retries) {2200RS_DBG("patch timerout, retry:\n");2201if (rtk_h5.host_last_cmd) {2202write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);2203RS_DBG("3-wire download patch re send:%d", retries);2204}2205retries++;2206alarm(3);2207return;2208}2209tcflush(serial_fd, TCIOFLUSH);2210RS_ERR("rtk get lmp version cmd complete event timed out\n");2211exit(1);2212}22132214static void rtk_get_lmp_version(int dd)2215{2216char bytes[READ_DATA_SIZE];2217int retlen;2218struct sigaction sa;2219/* send HCI_VENDOR_READ_RTK_ROM_VERISION_Command */2220uint8_t read_rom_patch_cmd[3] = {0x01, 0x10, 00};2221struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, read_rom_patch_cmd, 3, HCI_COMMAND_PKT); /* data: len+head: 4 */22222223if (rtk_h5.host_last_cmd) {2224skb_free(rtk_h5.host_last_cmd);2225rtk_h5.host_last_cmd = NULL;2226}22272228rtk_h5.host_last_cmd = nskb;22292230write(dd, nskb->data, nskb->data_len);2231ghci_version_cmd_state = cmd_has_sent;2232RS_DBG("RTK send HCI_VENDOR_READ_RTK_ROM_VERISION_Command\n");22332234alarm(0);2235memset(&sa, 0, sizeof(sa));2236sa.sa_flags = SA_NOCLDSTOP;2237sa.sa_handler = rtk_get_lmp_version_timeout;2238sigaction(SIGALRM, &sa, NULL);22392240alarm(3);2241while (ghci_version_cmd_state != event_received) {2242retlen = read_check(dd, &bytes, READ_DATA_SIZE);2243if (retlen == -1) {2244perror("read fail");2245return;2246}2247h5_recv(&rtk_h5, &bytes, retlen);2248}2249alarm(0);2250return;2251}22522253static void rtk_get_chip_type(int dd)2254{2255char bytes[READ_DATA_SIZE];2256int retlen;2257struct sigaction sa;2258uint8_t read_rom_patch_cmd[8] = {0x61, 0xfc, 0x05, 0x00, 0x94, 0xa0, 0x00, 0xb0};2259struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, read_rom_patch_cmd, 8, HCI_COMMAND_PKT); /* data: len+head: 4 */22602261if (rtk_h5.host_last_cmd) {2262skb_free(rtk_h5.host_last_cmd);2263rtk_h5.host_last_cmd = NULL;2264}22652266rtk_h5.host_last_cmd = nskb;22672268write(dd, nskb->data, nskb->data_len);2269gchip_type_cmd_state = cmd_has_sent;2270RS_DBG("RTK send HCI_VENDOR_READ_CHIP_TYPE Command");22712272alarm(0);2273memset(&sa, 0, sizeof(sa));2274sa.sa_flags = SA_NOCLDSTOP;2275sa.sa_handler = rtk_get_lmp_version_timeout;2276sigaction(SIGALRM, &sa, NULL);22772278alarm(3);2279while (gchip_type_cmd_state != event_received) {2280retlen = read_check(dd, &bytes, READ_DATA_SIZE);2281if (retlen == -1) {2282perror("read fail");2283return;2284}2285h5_recv(&rtk_h5, &bytes, retlen);2286}2287alarm(0);2288return;2289}22902291static int check_match_state(bt_hw_cfg_cb_t *cfg, uint32_t mask)2292{2293patch_info *patch_entry;2294int res = 0;22952296for (patch_entry = patch_table; patch_entry->lmp_subversion != LMP_SUBVERSION_NONE; patch_entry++) {2297if (patch_entry->lmp_subversion != cfg->lmp_subversion)2298continue;2299if ((patch_entry->hci_version_mask != HCI_VERSION_MASK_ALL) && ((patch_entry->hci_version_mask & (1 << cfg->hci_version)) == 0))2300continue;2301if ((patch_entry->hci_revision_mask != HCI_REVISION_MASK_ALL) && ((patch_entry->hci_revision_mask & (1 << cfg->hci_revision)) == 0))2302continue;2303if ((mask & PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE) && (patch_entry->chip_type_mask != CHIP_TYPE_MASK_ALL) && ((patch_entry->chip_type_mask & (1 << cfg->chip_type)) == 0))2304continue;2305res++;2306}2307RS_DBG("check_match_state return %d(cfg->lmp_subversion:0x%x cfg->hci_vesion:0x%x cfg->hci_revision:0x%x cfg->chip_type:0x%x mask:%08x)",2308res, cfg->lmp_subversion, cfg->hci_version, cfg->hci_revision, cfg->chip_type, mask);2309return res;2310}23112312static patch_info *get_patch_entry(bt_hw_cfg_cb_t *cfg)2313{2314patch_info *patch_entry;23152316RS_DBG("get_patch_entry(lmp_subversion:0x%x hci_vesion:0x%x cfg->hci_revision:0x%x chip_type:0x%x)",2317cfg->lmp_subversion, cfg->hci_version, cfg->hci_revision, cfg->chip_type);2318for (patch_entry = patch_table; patch_entry->lmp_subversion != LMP_SUBVERSION_NONE; patch_entry++) {2319if (patch_entry->lmp_subversion != cfg->lmp_subversion)2320continue;2321if ((patch_entry->hci_version_mask != HCI_VERSION_MASK_ALL) && ((patch_entry->hci_version_mask & (1 << cfg->hci_version)) == 0))2322continue;2323if ((patch_entry->hci_revision_mask != HCI_REVISION_MASK_ALL) && ((patch_entry->hci_revision_mask & (1<<cfg->hci_revision)) == 0))2324continue;2325if ((patch_entry->chip_type_mask != CHIP_TYPE_MASK_ALL) && ((patch_entry->chip_type_mask & (1<<cfg->chip_type)) == 0))2326continue;2327break;2328}2329RS_DBG("get_patch_entry return(patch_name:%s config_name:%s mac_offset:0x%x)",2330patch_entry->patch_name, patch_entry->config_name, patch_entry->mac_offset);2331return patch_entry;2332}23332334/**2335* Config realtek Bluetooth. The configuration parameter is get from config file and fw.2336*2337* @warning maybe only one of config file and fw file exists. The bt_addr arg is stored in "/data/btmac.txt"2338* or "/data/misc/bluetoothd/bt_mac/btmac.txt",2339*2340* @param fd uart file descriptor2341* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE2342* @param speed init_speed in uart struct2343* @param ti termios struct2344* @returns #0 on success2345*/2346static int rtk_config(int fd, int proto, int speed, struct termios *ti)2347{2348int config_len = -1, buf_len = -1, final_speed = 0;2349uint8_t *config_file_buf = NULL;2350uint8_t *buf = NULL;2351uint32_t baudrate = 0;23522353uint8_t *epatch_buf = NULL;2354struct rtk_epatch *epatch_info = NULL;2355struct rtk_epatch_entry current_entry;2356uint8_t need_download_fw = 1;2357patch_info *prtk_patch_file_info = NULL;23582359current_entry.start_offset = 0;2360current_entry.patch_length = 0;2361current_entry.chipID = 0;23622363/*2364* 1. if both config file and fw exists, use it and change rate according to config file2365* 2. if config file not exists while fw does, not change baudrate and only download fw2366* 3. if fw doesnot exist, only change rate to 3.25M or from config file if it exist. This case is only for early debug before any efuse is setting.2367*/23682369/* Get version from ROM */2370rtk_get_lmp_version(fd);2371if (check_match_state(&hw_cfg_cb, 0) > 1) {2372rtk_get_chip_type(fd);2373RS_DBG("lmp_subversion = 0x%x, hci_version = 0x%x, hci_revision = 0x%x, chip_type = 0x%x",2374hw_cfg_cb.lmp_subversion, hw_cfg_cb.hci_version, hw_cfg_cb.hci_revision, hw_cfg_cb.chip_type);2375}23762377prtk_patch_file_info = get_patch_entry(&hw_cfg_cb);23782379if (prtk_patch_file_info == NULL) {2380RS_ERR("lmp_version is %x, no matched project found!", hw_cfg_cb.lmp_subversion);2381need_download_fw = 0;2382goto FETCH_DONE;2383}23842385config_len = rtk_get_bt_config(&config_file_buf, &baudrate, prtk_patch_file_info);2386if (config_len < 0) {2387RS_ERR("Get Config file error, just use efuse settings");2388config_len = 0;2389}23902391buf_len = rtk_get_bt_firmware(&epatch_buf, config_len, prtk_patch_file_info);2392if (buf_len < 0) {2393RS_ERR("Get BT firmware error, continue without bt firmware");2394goto FETCH_DONE;2395}23962397if (hw_cfg_cb.lmp_subversion == ROM_LMP_8723a) {2398if (memcmp(epatch_buf, RTK_EPATCH_SIGNATURE, 8) == 0) {2399RS_ERR("8723as Check signature error!");2400need_download_fw = 0;2401goto FETCH_DONE;2402}24032404buf = malloc(buf_len);2405if (!buf) {2406RS_ERR("Can't alloc memory for fw&config, errno:%d", errno);2407buf_len = -1;2408goto FETCH_DONE;2409}24102411RS_DBG("8723as, fw copy direct");2412memcpy(buf, epatch_buf, buf_len);2413} else {2414/* Get version from ROM */2415rtk_get_eversion(fd); /* gEVersion is set. */2416RS_DBG("gEVersion=%d", gEVersion);2417/* check Extension Section Field */2418if (memcmp(epatch_buf + buf_len - config_len - 4, Extension_Section_SIGNATURE, 4) != 0) {2419RS_ERR("Check Extension_Section_SIGNATURE error! do not download fw");2420need_download_fw = 0;2421goto FETCH_DONE;2422}24232424if (memcmp(epatch_buf, RTK_EPATCH_SIGNATURE, 8) != 0) {2425RS_DBG("Check signature error!");2426need_download_fw = 0;2427goto FETCH_DONE;2428}24292430int i = 0;2431uint32_t value_t = 0;2432epatch_info = (struct rtk_epatch *)epatch_buf;2433value_t = le32_to_cpu(epatch_info->fm_version);2434epatch_info->fm_version = (uint32_t)value_t;2435value_t = le16_to_cpu(epatch_info->number_of_total_patch);2436epatch_info->number_of_total_patch = (uint16_t)value_t;2437RS_DBG("fm_version = 0x%x", epatch_info->fm_version);2438RS_DBG("number_of_total_patch = %d", epatch_info->number_of_total_patch);2439/* get right epatch entry */2440for (i = 0; i < epatch_info->number_of_total_patch; i++) {2441if (le16_to_cpu(*(uint16_t *)(epatch_buf + 14 + 2 * i)) == gEVersion + 1) {2442current_entry.chipID = gEVersion + 1;2443current_entry.patch_length = le16_to_cpu(*(uint16_t *)(epatch_buf + 14 + 2 * epatch_info->number_of_total_patch + 2 * i));2444current_entry.start_offset = le32_to_cpu(*(uint32_t *)(epatch_buf + 14 + 4 * epatch_info->number_of_total_patch + 4 * i));2445break;2446}2447}2448RS_DBG("chipID = %d", current_entry.chipID);2449RS_DBG("patch_length = 0x%x", current_entry.patch_length);2450RS_DBG("start_offset = 0x%x", current_entry.start_offset);2451/* get right version patch: buf, buf_len */2452buf_len = current_entry.patch_length + config_len;2453RS_DBG("buf_len = 0x%x", buf_len);2454buf = malloc(buf_len);2455if (!buf) {2456RS_ERR("Can't alloc memory for multi fw&config, errno:%d", errno);2457buf_len = -1;2458goto FETCH_DONE;2459}2460memcpy(buf, &epatch_buf[current_entry.start_offset], current_entry.patch_length);2461value_t = cpu_to_le32(epatch_info->fm_version);2462epatch_info->fm_version = (uint32_t)value_t;2463memcpy(&buf[current_entry.patch_length-4], &epatch_info->fm_version, 4);2464value_t = cpu_to_le32(epatch_info->fm_version);2465epatch_info->fm_version = value_t;2466}24672468if (config_len) {2469memcpy(&buf[buf_len - config_len], config_file_buf, config_len);2470}24712472FETCH_DONE:2473free(epatch_buf);2474epatch_buf = NULL;2475if (config_file_buf)2476free(config_file_buf);24772478RS_DBG("Fw:%s exists, config file:%s exists", (buf_len > 0) ? "" : "not", (config_len > 0) ? "" : "not");2479if ((buf_len > 0) && (config_len == 0)) {2480rtk_h5.link_estab_state = H5_PATCH;2481goto DOWNLOAD_FW;2482}24832484/* change baudrate if needed */2485if (baudrate == 0) {2486uart_speed_to_rtk_speed(speed, &baudrate);2487RS_DBG("Since no config file to set uart baudrate, so use user input parameters:%x, %x", (int)speed, (uint32_t)baudrate);2488} else2489rtk_speed_to_uart_speed(baudrate, (uint32_t *)&gFinalSpeed);24902491if (proto == HCI_UART_3WIRE)2492rtk_vendor_change_speed_h5(fd, baudrate);2493else2494rtk_vendor_change_speed_h4(fd, baudrate);24952496usleep(50000);2497final_speed = gFinalSpeed ? gFinalSpeed : speed;2498RS_DBG("final_speed %d\n", final_speed);2499if (set_speed(fd, ti, final_speed) < 0) {2500RS_ERR("Can't set baud rate:%x, %x, %x", final_speed, gFinalSpeed, speed);2501return -1;2502}25032504if (gHwFlowControlEnable) {2505RS_DBG("Hw Flow Control enable");2506ti->c_cflag |= CRTSCTS;2507} else {2508RS_DBG("Hw Flow Control disable");2509ti->c_cflag &= ~CRTSCTS;2510}2511RS_DBG("Hw Flow Control do not enable before download fw! ");25122513/* wait for while for controller to setup */2514usleep(10000);25152516DOWNLOAD_FW:2517if (buf && (buf_len > 0) && (need_download_fw)) {2518/* baudrate 0 means no change baudrate send */2519memset(&rtk_patch, 0, sizeof(rtk_patch));2520rtk_patch.nRxIndex = -1;25212522rtk_download_fw_config(fd, buf, buf_len, baudrate, proto, ti);2523free(buf);2524}2525RS_DBG("Init Process finished");2526return 0;2527}25282529/**2530* Init uart by realtek Bluetooth.2531*2532* @param fd uart file descriptor2533* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE2534* @param speed init_speed in uart struct2535* @param ti termios struct2536* @returns #0 on success, depend on rtk_config2537*/2538int rtk_init(int fd, int proto, int speed, struct termios *ti)2539{2540RS_DBG("Realtek hciattach version %s \n", RTK_VERSION);25412542if (proto == HCI_UART_3WIRE) { /*h4 will do nothing for init */2543rtk_init_h5(fd, ti);2544}2545return rtk_config(fd, proto, speed, ti);2546}25472548/**2549* Post uart by realtek Bluetooth. If gFinalSpeed is set, set uart speed with it.2550*2551* @param fd uart file descriptor2552* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE2553* @param ti termios struct2554* @returns #0 on success.2555*/2556int rtk_post(int fd, int proto, struct termios *ti)2557{2558if (gFinalSpeed) {2559return set_speed(fd, ti, gFinalSpeed);2560}2561return 0;2562}256325642565