/* * * Realtek Bluetooth USB driver * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include /*********************************** ** Realtek - For coexistence ** ***********************************/ #define BTRTL_HCIUSB 0 #define BTRTL_HCIUART 1 #define BTRTL_HCI_IF BTRTL_HCIUSB #define TRUE 1 #define FALSE 0 #define CONNECT_PORT 30001 #define CONNECT_PORT_WIFI 30000 #define invite_req "INVITE_REQ" #define invite_rsp "INVITE_RSP" #define attend_req "ATTEND_REQ" #define attend_ack "ATTEND_ACK" #define wifi_leave "WIFI_LEAVE" #define leave_ack "LEAVE_ACK" #define bt_leave "BT_LEAVE" #define HCI_OP_PERIODIC_INQ 0x0403 #define HCI_EV_LE_META 0x3e #define HCI_EV_LE_CONN_COMPLETE 0x01 #define HCI_EV_LE_CONN_UPDATE_COMPLETE 0x03 //vendor cmd to fw #define HCI_VENDOR_ENABLE_PROFILE_REPORT_COMMAND 0xfc18 #define HCI_VENDOR_SET_PROFILE_REPORT_COMMAND 0xfc19 #define HCI_VENDOR_MAILBOX_CMD 0xfc8f #define HCI_VENDOR_SET_BITPOOL 0xfc51 //subcmd to fw #define HCI_VENDOR_SUB_CMD_WIFI_CHANNEL_AND_BANDWIDTH_CMD 0x11 #define HCI_VENDOR_SUB_CMD_WIFI_FORCE_TX_POWER_CMD 0x17 #define HCI_VENDOR_SUB_CMD_BT_ENABLE_IGNORE_WLAN_ACT_CMD 0x1B #define HCI_VENDOR_SUB_CMD_BT_REPORT_CONN_SCO_INQ_INFO 0x23 #define HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_STATUS_INFO 0x27 #define HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_ENABLE 0x28 #define HCI_VENDOR_SUB_CMD_BT_SET_TXRETRY_REPORT_PARAM 0x29 #define HCI_VENDOR_SUB_CMD_BT_SET_PTATABLE 0x2A #define HCI_VENDOR_SUB_CMD_SET_BT_PSD_MODE 0x31 #define HCI_VENDOR_SUB_CMD_SET_BT_LNA_CONSTRAINT 0x32 #define HCI_VENDOR_SUB_CMD_GET_AFH_MAP_L 0x40 #define HCI_VENDOR_SUB_CMD_GET_AFH_MAP_M 0x41 #define HCI_VENDOR_SUB_CMD_GET_AFH_MAP_H 0x42 #define HCI_VENDOR_SUB_CMD_RD_REG_REQ 0x43 #define HCI_VENDOR_SUB_CMD_WR_REG_REQ 0x44 #define HCI_EV_VENDOR_SPECIFIC 0xff //sub event from fw start #define HCI_VENDOR_PTA_REPORT_EVENT 0x24 #define HCI_VENDOR_PTA_AUTO_REPORT_EVENT 0x25 //vendor cmd to wifi driver #define HCI_GRP_VENDOR_SPECIFIC (0x3f << 10) #define HCI_OP_HCI_EXTENSION_VERSION_NOTIFY (0x0100 | HCI_GRP_VENDOR_SPECIFIC) #define HCI_OP_BT_OPERATION_NOTIFY (0x0102 | HCI_GRP_VENDOR_SPECIFIC) #define HCI_OP_HCI_BT_INFO_NOTIFY (0x0106 | HCI_GRP_VENDOR_SPECIFIC) #define HCI_OP_HCI_BT_COEX_NOTIFY (0x0107 | HCI_GRP_VENDOR_SPECIFIC) #define HCI_OP_HCI_BT_PATCH_VER_NOTIFY (0x0108 | HCI_GRP_VENDOR_SPECIFIC) #define HCI_OP_HCI_BT_AFH_MAP_NOTIFY (0x0109 | HCI_GRP_VENDOR_SPECIFIC) #define HCI_OP_HCI_BT_REGISTER_VALUE_NOTIFY (0x010a | HCI_GRP_VENDOR_SPECIFIC) //bt info reason to wifi #define HOST_RESPONSE 0 //Host response when receive the BT Info Control Event #define POLLING_RESPONSE 1 //The BT Info response for polling by BT firmware. #define AUTO_REPORT 2 //BT auto report by BT firmware. #define STACK_REPORT_WHILE_DEVICE_D2 3 //Stack report when BT firmware is under power save state(ex:D2) // vendor event from wifi #define RTK_HS_EXTENSION_EVENT_WIFI_SCAN 0x01 #define RTK_HS_EXTENSION_EVENT_RADIO_STATUS_NOTIFY 0x02 #define RTK_HS_EXTENSION_EVENT_HCI_BT_INFO_CONTROL 0x03 #define RTK_HS_EXTENSION_EVENT_HCI_BT_COEX_CONTROL 0x04 //op code from wifi #define BT_PATCH_VERSION_QUERY 0x00 #define IGNORE_WLAN_ACTIVE_CONTROL 0x01 #define LNA_CONSTRAIN_CONTROL 0x02 #define BT_POWER_DECREASE_CONTROL 0x03 #define BT_PSD_MODE_CONTROL 0x04 #define WIFI_BW_CHNL_NOTIFY 0x05 #define QUERY_BT_AFH_MAP 0x06 #define BT_REGISTER_ACCESS 0x07 //bt operation to notify #define BT_OPCODE_NONE 0 #define BT_OPCODE_INQUIRY_START 1 #define BT_OPCODE_INQUIRY_END 2 #define BT_OPCODE_PAGE_START 3 #define BT_OPCODE_PAGE_SUCCESS_END 4 #define BT_OPCODE_PAGE_UNSUCCESS_END 5 #define BT_OPCODE_PAIR_START 6 #define BT_OPCODE_PAIR_END 7 #define BT_OPCODE_ENABLE_BT 8 #define BT_OPCODE_DISABLE_BT 9 #define HCI_EXTENSION_VERSION 0x0004 #define HCI_CMD_PREAMBLE_SIZE 3 #define PAN_PACKET_COUNT 5 #define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;} #define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);} #define PSM_SDP 0x0001 #define PSM_RFCOMM 0x0003 #define PSM_PAN 0x000F #define PSM_HID 0x0011 #define PSM_HID_INT 0x0013 #define PSM_AVCTP 0x0017 #define PSM_AVDTP 0x0019 #define PSM_FTP 0x1001 #define PSM_BIP 0x1003 #define PSM_OPP 0x1015 //--add more if needed--// enum { profile_sco = 0, profile_hid = 1, profile_a2dp = 2, profile_pan = 3, profile_hid_interval = 4, profile_hogp = 5, profile_voice = 6, profile_sink = 7, profile_max = 8 }; #define A2DP_SIGNAL 0x01 #define A2DP_MEDIA 0x02 //profile info data typedef struct { struct list_head list; uint16_t handle; uint16_t psm; uint16_t dcid; uint16_t scid; uint8_t profile_index; uint8_t flags; } rtk_prof_info, *prtk_prof_info; //profile info for each connection typedef struct rtl_hci_conn { struct list_head list; uint16_t handle; uint8_t type; // 0:l2cap, 1:sco/esco, 2:le uint8_t profile_bitmap; int8_t profile_refcount[8]; } rtk_conn_prof, *prtk_conn_prof; #ifdef RTB_SOFTWARE_MAILBOX struct rtl_btinfo { u8 cmd; u8 len; u8 data[6]; }; #define RTL_BTINFO_LEN (sizeof(struct rtl_btinfo)) /* typedef struct { * uint8_t cmd_index; * uint8_t cmd_length; * uint8_t link_status; * uint8_t retry_cnt; * uint8_t rssi; * uint8_t mailbox_info; * uint16_t acl_throughput; * } hci_linkstatus_report; */ typedef struct { uint8_t type; uint32_t offset; uint32_t value; } hci_mailbox_register; struct rtl_btinfo_ctl { uint8_t polling_enable; uint8_t polling_time; uint8_t autoreport_enable; }; #endif /* RTB_SOFTWARE_MAILBOX */ #define MAX_LEN_OF_HCI_EV 32 #define NUM_RTL_HCI_EV 32 struct rtl_hci_ev { __u8 data[MAX_LEN_OF_HCI_EV]; __u16 len; struct list_head list; }; #define L2_MAX_SUBSEC_LEN 128 #define L2_MAX_PKTS 16 struct rtl_l2_buff { __u8 data[L2_MAX_SUBSEC_LEN]; __u16 len; __u16 out; struct list_head list; }; struct rtl_coex_struct { struct list_head conn_hash; //hash for connections struct list_head profile_list; //hash for profile info struct hci_dev *hdev; #ifdef RTB_SOFTWARE_MAILBOX struct socket *udpsock; struct sockaddr_in addr; struct sockaddr_in wifi_addr; struct timer_list polling_timer; #endif struct timer_list a2dp_count_timer; struct timer_list pan_count_timer; struct timer_list hogp_count_timer; #ifdef RTB_SOFTWARE_MAILBOX struct workqueue_struct *sock_wq; struct delayed_work sock_work; #endif struct workqueue_struct *fw_wq; struct delayed_work fw_work; struct delayed_work l2_work; #ifdef RTB_SOFTWARE_MAILBOX struct sock *sk; #endif struct urb *urb; spinlock_t spin_lock_sock; spinlock_t spin_lock_profile; uint32_t a2dp_packet_count; uint32_t pan_packet_count; uint32_t hogp_packet_count; uint32_t voice_packet_count; uint8_t profile_bitmap; uint8_t profile_status; int8_t profile_refcount[8]; uint8_t ispairing; uint8_t isinquirying; uint8_t ispaging; #ifdef RTB_SOFTWARE_MAILBOX uint8_t wifi_state; uint8_t autoreport; uint8_t polling_enable; uint8_t polling_interval; uint8_t piconet_id; uint8_t mode; uint8_t afh_map[10]; #endif uint16_t hci_reversion; uint16_t lmp_subversion; #ifdef RTB_SOFTWARE_MAILBOX uint8_t wifi_on; uint8_t sock_open; #endif unsigned long cmd_last_tx; /* hci ev buff */ struct list_head ev_used_list; struct list_head ev_free_list; spinlock_t rxlock; __u8 pkt_type; __u16 expect; __u8 *tbuff; __u16 elen; __u8 back_buff[HCI_MAX_EVENT_SIZE]; /* l2cap rx buff */ struct list_head l2_used_list; struct list_head l2_free_list; /* buff addr and size */ spinlock_t buff_lock; unsigned long pages_addr; unsigned long buff_size; #define RTL_COEX_RUNNING (1 << 0) unsigned long flags; }; #ifdef __LITTLE_ENDIAN struct sbc_frame_hdr { uint8_t syncword:8; /* Sync word */ uint8_t subbands:1; /* Subbands */ uint8_t allocation_method:1; /* Allocation method */ uint8_t channel_mode:2; /* Channel mode */ uint8_t blocks:2; /* Blocks */ uint8_t sampling_frequency:2; /* Sampling frequency */ uint8_t bitpool:8; /* Bitpool */ uint8_t crc_check:8; /* CRC check */ } __attribute__ ((packed)); /* NOTE: The code is copied from pa. * only the bit field in 8-bit is affected by endian, not the 16-bit or 32-bit. * why? */ struct rtp_header { unsigned cc:4; unsigned x:1; unsigned p:1; unsigned v:2; unsigned pt:7; unsigned m:1; uint16_t sequence_number; uint32_t timestamp; uint32_t ssrc; uint32_t csrc[0]; } __attribute__ ((packed)); #else /* big endian */ struct sbc_frame_hdr { uint8_t syncword:8; /* Sync word */ uint8_t sampling_frequency:2; /* Sampling frequency */ uint8_t blocks:2; /* Blocks */ uint8_t channel_mode:2; /* Channel mode */ uint8_t allocation_method:1; /* Allocation method */ uint8_t subbands:1; /* Subbands */ uint8_t bitpool:8; /* Bitpool */ uint8_t crc_check:8; /* CRC check */ } __attribute__ ((packed)); struct rtp_header { unsigned v:2; unsigned p:1; unsigned x:1; unsigned cc:4; unsigned m:1; unsigned pt:7; uint16_t sequence_number; uint32_t timestamp; uint32_t ssrc; uint32_t csrc[0]; } __attribute__ ((packed)); #endif /* __LITTLE_ENDIAN */ void rtk_btcoex_parse_event(uint8_t *buffer, int count); void rtk_btcoex_parse_cmd(uint8_t *buffer, int count); void rtk_btcoex_parse_l2cap_data_tx(uint8_t *buffer, int count); void rtk_btcoex_parse_l2cap_data_rx(uint8_t *buffer, int count); void rtk_btcoex_open(struct hci_dev *hdev); void rtk_btcoex_close(void); void rtk_btcoex_probe(struct hci_dev *hdev); void rtk_btcoex_init(void); void rtk_btcoex_exit(void);