⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hci.c

📁 blue tooth protocol stack source code
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * hci.c -- Implementation of Bluetooth Host Controller Interface  *          (UART transport layer) * * Copyright (C) 2000, 2001  Axis Communications AB * * Author: Mats Friden <mats.friden@axis.com> * * 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. * * Exceptionally, Axis Communications AB grants discretionary and * conditional permissions for additional use of the text contained * in the company's release of the AXIS OpenBT Stack under the * provisions set forth hereunder. * * Provided that, if you use the AXIS OpenBT Stack with other files, * that do not implement functionality as specified in the Bluetooth * System specification, to produce an executable, this does not by * itself cause the resulting executable to be covered by the GNU * General Public License. Your use of that executable is in no way * restricted on account of using the AXIS OpenBT Stack code with it. * * This exception does not however invalidate any other reasons why * the executable file might be covered by the provisions of the GNU * General Public License. * * $Id: hci.c,v 1.187 2001/10/16 14:57:10 pkj Exp $ * *//****************** INCLUDE FILES SECTION ***********************************/#define __NO_VERSION__ /* don't define kernel_version in module.h */#ifdef __KERNEL__#include <linux/config.h>#include <linux/bluetooth/sysdep-2.1.h>#include <linux/malloc.h>#include <linux/timer.h>#include <linux/bluetooth/hci.h>#include <linux/bluetooth/hci_internal.h>#include <linux/bluetooth/btdebug.h>#include <linux/bluetooth/bluetooth.h>#include <linux/bluetooth/l2cap.h>#include <linux/bluetooth/l2cap_con.h>#include <linux/bluetooth/tcs.h>#include <linux/bluetooth/btmem.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/bluetooth/sec_client.h>#include <asm/io.h>#include <asm/byteorder.h>#include <asm/unaligned.h>#else /* user mode */#include <stdlib.h>#include <string.h>#include <errno.h>#include <asm/unaligned.h>#include "include/bluetooth.h"#include "include/hci.h"#include "include/hci_internal.h"#include "include/btdebug.h"#include "include/l2cap.h"#include "include/l2cap_con.h"#include "include/btmem.h"#include "include/tcs.h"#include "include/sec_client.h"#include "include/local.h"#endif/****************** CONSTANT AND MACRO SECTION ******************************/#define ACL_LINK 1#define SCO_LINK 0#define HCI_BLOCK 1#define HCI_NON_BLOCK 0/* If using host flow control, this is what we can store in our inbuffers */#define HCI_ACL_LEN 500#define HCI_SCO_LEN 255#define HCI_ACL_NUM 4#define HCI_SCO_NUM 2/* Now we will define all the different packet types */#define DM1 0x0008#define DM3 0x0400#define DM5 0x4000#define DH1 0x0010#define DH3 0x0800#define DH5 0x8000/* master slave switch stuff */#define MS_SWITCH_BECOME_MASTER 0x00#define MS_SWITCH_REMAIN_SLAVE  0x01#define DONT_ALLOW_ROLE_SWITCH  0x00#define ALLOW_ROLE_SWITCH       0x01#define HCI_SYNC_FIX#ifdef HCI_EMULATION#define ACL_NUM 10#define ACL_LEN 800 #define SCO_NUM 2#define SCO_LEN 100#define HCI_HDL 0#define ACL_CON 0x1#endif#define USE_NCPTIMER #define NCP_TIMEOUT (2*HZ)/****************** TYPE DEFINITION SECTION *********************************//* cmd_t and cmd_buf are structures used to handle the queue of commands   waiting to be sent on the serial port */typedef struct cmd_t {	u8* data;	u8 len; /* max 255 */} cmd_t;struct cmd_buf {	u32 first_free; /* index in cmd_buf */	u32 next_to_send; /* index in cmd_buf */	u8 count;	cmd_t buf[NBR_CMD_BUFS];};/* These are the states the state machine in hci_receive_data can be in */enum states { WAIT_FOR_PACKET_TYPE, WAIT_FOR_EVENT_TYPE, WAIT_FOR_EVENT_LENGTH,	      WAIT_FOR_EVENT_PARAM, WAIT_FOR_ACL_HDR, WAIT_FOR_ACL_DATA, 	      WAIT_FOR_SCO_HDR, WAIT_FOR_SCO_DATA, WAIT_FOR_TIMEOUT };#ifdef HCI_EMULATION/* If we are using the HCI emulation, we need a definition of the event packet   to, see part H:1 chapter 4.4.2 of the baseband core specification for a   description of the HCI event packet. */typedef struct event_struct {	u8 pkt_type;	u8 event_type;	u8 len;	u8 data[0];} __attribute__ ((packed)) event_struct;#endif/****************** LOCAL FUNCTION DECLARATION SECTION **********************/static void process_event(u8 *buf, u32 len, u32 event_code);static void process_return_param(u8 *buf);static void process_acl_data(hci_in_buffer* in_buf, u32 pb_flag);static void process_sco_packet(u8 *data, u32 hci_hdl, u32 len);static hci_in_buffer* get_inbuffer(u32 hci_hdl);static hci_in_buffer* get_free_inbuffer(void);static u32 send_acl_packet(bt_tx_buf *tx_buf);static void set_acl_hdr(u8 *data, u32 len, u8 pb, u8 bc, u32 hci_hdl);static u16 hci_handle(void *data);static cmd_t* get_next_cmd(void); static s32 insert_cmd(u8* cmd, u8 len); static void init_cmd_buf(void);static void send_cmd_queue(void);static void update_nhcp(s32 nhcp);static s32 send_inq_cmd_block(u8 *cmd, u8 len, u8 inq_len);#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGERstatic u8* get_bd(u16 con_hdl);#endifstatic s32 get_con_hdl(u8 *bd);/* Link Control Commands */static s32 create_connection(u8 *bd, u32 pkt_type, u8 psrm, u8 psm, u32 c_off, u32 rol_sw);static s32 disconnect(u32 hdl, u8 reason);static s32 accept_connection_request(u8 bd_addr[], u8 role);static s32 reject_connection_request(u8 bd_addr[], u32 reason);static s32 change_connection_packet_type(u32 hci_hdl, u32 pkt_type);static s32 remote_name_request(u8 *bd);/* Link Policy Commands */static s32 role_discovery(u16 con_hdl);static s32 write_link_policy_settings(u16 con_hdl, u16 settings);/* Host Controller and Baseband Commands */static s32 write_inquiryscan_activity(u32 interval, u32 wind);static s32 write_automatic_flush_timeout(u16 con_hdl, u16 n);static s32 hci_set_host_controller_flow_control(u32 enable);static s32 hci_host_buffer_size(u16 acl_len, u8 sco_len, u16 acl_num, u16 sco_num);static s32 host_nbrcompleted_packets(u32 hci_hdl, u32 nbr_of_packets);/* Informational Parameters (HCI_IP) *//* Other functions */static s32 hci_update_load_factor(void);static s32 hci_read_buffer_size(s32 block); static void set_hci_con(u8 *bd, s32 con_hdl);static void set_hci_con_name(u8 *bd, u8 *name);static void reset_hci_con_bd(u16 con_hdl);#ifdef USE_NCPTIMERstatic void start_ncp_timer(void);static void release_ncp_timer(void);#endif#define USE_INQTIMER 1#ifdef USE_INQTIMERstatic void start_inq_timer(u8 inq_len);static void release_inq_timer(void);#endif#ifdef __KERNEL__#ifdef USE_NCPTIMERstatic void ncp_timeout(unsigned long ptr);#endifstatic void cmd_timeout(unsigned long ptr);#ifdef USE_INQTIMERstatic void inq_timeout(unsigned long ptr);#endif#endif#ifdef HCI_EMULATIONstatic void hci_emulator(u8 *data, u32 len);static void command_handler(u8 *data);static s32 set_cmd_status_event(event_struct *event, u8 *cmd);static s32 set_con_req_event(event_struct *event, u8 *bd, u8 con_type);static s32 set_con_cpl_event(event_struct *event, u8 status, u8 *bd,			     u16 hci_hdl,u8 con_type);static s32 set_discon_cpl_event(event_struct *event, u16 hci_hdl, u8 reason);#endifstatic void send_acl_data_task(void);/****************** LOCAL VARIABLE DECLARATION SECTION **********************/static struct cmd_buf cmd_buf;/* Struct used for sending command packets */cmd_pkt c_pkt;/* The states for the switch-statement in hci_receive_data fuction */static enum states state;/* General HCI controller struct, contains vital information about buffer    sizes and connections */hci_controller hci_ctrl = {{0, 0, 0, 0, 0}};			 #ifdef __KERNEL__#ifdef USE_NCPTIMERstatic struct timer_list hci_ncp_timer;#endifstatic struct timer_list hci_cmd_timer;#ifdef USE_INQTIMERstatic struct timer_list hci_inq_timer;#endif#ifdef USE_NCPTIMERstatic struct hw_info {	u32 max_acl_num;	u32 acl_num_count; /* since last timeout */} hw;#endif/* ================================= */static struct tq_struct send_cmd_task;static struct tq_struct send_data_task;/* semaphore for protecting shared data */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)static struct semaphore hci_cmd_semaphore = MUTEX;static struct semaphore hci_inq_semaphore = MUTEX;#elsestatic struct semaphore hci_cmd_semaphore;static struct semaphore hci_inq_semaphore;#endif /* LINUX_VERSION_CODE */#endif /* __KERNEL__ */static u32 hci_cmd_pending = 0;static u32 hci_inq_pending = 0;static u8 hci_inq_aborted = 0;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)struct wait_queue *hci_wq = NULL;struct wait_queue *inq_wq = NULL;struct wait_queue *set_baudrate_wq = NULL;struct wait_queue *test_wq = NULL;#elsewait_queue_head_t hci_wq;wait_queue_head_t inq_wq;wait_queue_head_t set_baudrate_wq;wait_queue_head_t test_wq;#endif /* LINUX_VERSION_CODE */static s32 test_wq_active = 0;static s32 result_param;static struct inquiry_results *inq_res = NULL;static s32 test_hci_hdl;/* temp solution to handle m/s switch */static s32 force_msswitch = 0;static s32 i_am_initiator = 0;/* In order to change load factor, store the other class of device parameters */static u8 class_of_device[3];/* If maximum BT connections is not set from above, use 7 as default */int bt_max_connections = 7;/****************** FUNCTION DEFINITION SECTION *****************************//* * Parses the serial data and sends it to either the parse_acl_packet,  * parse_sco_packet or the parse_event_packet, depending on the packet type */voidhci_receive_data(u8* data, u32 count){	static u32 event_len;	static u32 data_len;	static u32 event_type;	static u32 pb_flag;	static u32 bc_flag;	static u32 hci_hdl;	static u8 event_buf[256];	static u8 hdr[4];	static hci_in_buffer *in_buf;	static u32 tmp_pos;	u32 c;     /* Temporary variable for index calculations */   	u8 *buf; /* Temporary pointer to the incoming data */	u32 tmp_data_len; 	PRINTPKT(__FUNCTION__ ": ", data, count);  	tmp_data_len = count;	buf = data;	/* Here we get a chunk of data from the serial port. When a complete 	   packet is received it is copied into a buffer and sent to the 	   processing function */  	D_INDATA(__FUNCTION__ ": hci-%d\n", tmp_data_len);	while (count > 0) {		switch (state) {					  /* The first byte will tell us whether it is an event or a		     data packet */		case WAIT_FOR_PACKET_TYPE:			D_STATE(__FUNCTION__ ": WAIT_FOR_PACKET_TYPE\n");			tmp_pos = 0;			switch(*buf) {			case EVENT_PKT: state = WAIT_FOR_EVENT_TYPE; break;			case ACL_PKT: state = WAIT_FOR_ACL_HDR; break;			case SCO_PKT: state = WAIT_FOR_SCO_HDR; break;			default:				D_ERR(__FUNCTION__ ": discarding %d bytes\n",				      count);				/* An unrecognized HCI header type is usually a				 * sign of a problem with the lower level 				 * driver. For example, if the UART drops some				 * bytes due to high interrupt latency. In this				 * case we'll try to resync by just dropping 				 * this buffer and trying again at the start of				 * the next one.				 * --gmcnutt				 */				return;			}			buf++;			count--;			break;			/* If it is an event packet we wait for the next byte			   which tell us which kind of event it is */ 		case WAIT_FOR_EVENT_TYPE:			D_STATE(__FUNCTION__ ": WAIT_FOR_EVENT_TYPE\n");			event_type = *buf;			state = WAIT_FOR_EVENT_LENGTH;			buf++;			count--;			break;			/* If it is an event the length-field is one byte */		case WAIT_FOR_EVENT_LENGTH:			D_STATE(__FUNCTION__ ": WAIT_FOR_EVENT_LENGTH\n");			event_len = *buf;			buf++;			count--;			/* If we don't check this and the lower level driver			   gives us some trashed values then we might write			   beyond the end of our event buffer in a memcpy 			   below.			   --gmcnutt			 */			if (event_len > sizeof(event_buf)) {				D_ERR(__FUNCTION__ ": %d is too big for our "\				      "event buffer -- discarding buffer\n",				      event_len);				state = WAIT_FOR_PACKET_TYPE;				return;			}			if (event_len <= count) {				process_event(buf, event_len, event_type);				buf += event_len;				count -= event_len;				state = WAIT_FOR_PACKET_TYPE;			} else {				state = WAIT_FOR_EVENT_PARAM;			}			break;			/* Before we can parse the event, we wait for the			   whole event */		case WAIT_FOR_EVENT_PARAM:			D_STATE(__FUNCTION__ ": WAIT_FOR_EVENT_PARAM\n");			if (tmp_pos < event_len) {				c = MIN(count, event_len - tmp_pos);				memcpy(event_buf + tmp_pos, buf, c);				tmp_pos += c;				count -= c;				buf += c;				if (tmp_pos == event_len) {					process_event(event_buf, event_len,						      event_type);					state = WAIT_FOR_PACKET_TYPE;				}			}			break;			/* Here we wait for the whole data header, four bytes*/		case WAIT_FOR_ACL_HDR:			D_STATE(__FUNCTION__ ": WAIT_FOR_ACL_HDR\n");			c = MIN(count, ACL_HDR_LEN - tmp_pos);			memcpy(hdr + tmp_pos, buf, c);			tmp_pos += c;			buf += c;			count -= c;			if (tmp_pos == ACL_HDR_LEN) {				u32 tmp_hdr = le32_to_cpuu(hdr);				hci_hdl = GET_BITS(tmp_hdr, 0, 12);				pb_flag = GET_BITS(tmp_hdr, 12, 2);				bc_flag = GET_BITS(tmp_hdr, 14, 2);				data_len = GET_BITS(tmp_hdr, 16, 16);				/* Check the length to make sure we won't 				   overrun in_buf->buf_ptr in a memcpy later.				   --gmcnutt				 */				if (data_len > HCI_IN_SIZE) {					D_ERR(__FUNCTION__ ": %d is too big "\					      "for our HCI input buffers -- "\					      "discarding buffer\n",					      data_len);					state = WAIT_FOR_PACKET_TYPE;					return;				}				if (pb_flag == L2CAP_FRAME_START) {					D_REC(__FUNCTION__ ": New frame\n");					in_buf = get_free_inbuffer();					if (in_buf) {						in_buf->nbr_of_hci_pkt = 1;						in_buf->hci_hdl = hci_hdl;					}					} else {					D_REC(__FUNCTION__ ": Cont frame\n");					in_buf = get_inbuffer(hci_hdl);					if (in_buf) {						in_buf->nbr_of_hci_pkt++;					}				}				host_nbrcompleted_packets(hci_hdl, 1);				/* When we change state we reset data_index,				   because we are using separate buffers for

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -