📄 hci.c
字号:
/*
********************************************************************************
*
* Embedded Systems Building Blocks
* Complete and Ready-to-use Modules in C
*
* HCI DRIVERS
*
* (c) Copyright 2004,chenna,watertek Shenzhen
* All Rights Reserved
*
*Filename : hci.c
*Programmer : chenna
********************************************************************************
* DESCRIPTION
*
********************************************************************************
*/
/*
********************************************************************************
* INCLUDE FILES
********************************************************************************
*/
#include "HCI.H"
#include "sd_extr.h"
/*
********************************************************************************
* LOCAL CONSTANTS
********************************************************************************
*/
/*
********************************************************************************
* GLOBAL VARIABLES
********************************************************************************
*/
/*
********************************************************************************
* LOCAL FUNCTIONS PROTOTYPES
********************************************************************************
*/
/*
********************************************************************************
* GLOBAL FUNCTIONS PROTOTYPES
********************************************************************************
*/
/*
********************************************************************************
*
*
*Description :
*Arguments :
*Retruns :
********************************************************************************
*/
/*
********************************************************************************
* 把指定长度的数据从源地址拷贝到目的地址
* 功 能:把指定长度的数据从源地址拷贝到目的地址
********************************************************************************
*/
int __bt_mem_cpy(void * dst,void *src,int len)
{
int i;
for(i=0;i<len;i++)
{
*((char*)dst+i) = *((char*)src+i);
}
return 0;
}
/*
********************************************************************************
* 地址的比较
* 功 能:比较两断内存的地址是否相等,如果相等就返回0,否则返回-1;
********************************************************************************
*/
int __bt_mem_cmp(void* buff1,void* buff2,int length)
{
int i;
for(i=0;i<length;i++)
{
if(!(*((char*)buff1+i) == (*((char*)buff2+i))))
return -1;
}
return 0;
}
/*
********************************************************************************
* 将某块内存设置成指定的数据
* 功 能:将以buff为起始的count个字节设置为数据ch
********************************************************************************
*/
void __bt_mem_set(void *buff,char ch,unsigned count)
{
int i;
for(i =0;i<count;i++)
{
*((char *)(buff)+i) =(char) ch;
}
}
/*
********************************************************************************
* 大小模式的转换
* 功 能:实现半字的高低两byte数据的交换,即实现大小模式的转换
********************************************************************************
*/
UINT16 __host_to_hci_16(UINT16 i)
{
//This function is used when the host and hci communications a 2 bytes logic block.this function can covert the byte order to the correct
/*
int temp;
temp = (i&0xff)<<8;
i =temp| (i>>8);*/
return i;
}
/*
********************************************************************************
* 大小模式的转换
* 功 能:实现半字的高低两byte数据的交换,即实现大小模式的转换
********************************************************************************
*/
UINT16 __hci_to_host_16(UINT16 i)
{
i =__host_to_hci_16(i);
return i;
}
/*
********************************************************************************
* 输出
* 功 能:将HCI_Tx_buff[1024]里面的内容输出出来,通过AXD的semihosting功能,输出在AXD的console控制台里面
********************************************************************************
*/
__inline int HCI_Put_char(struct hci_dev *hdev,char ch)
{
int new_write;
new_write=hdev->HCI_tx_buffer_write+1;
if(new_write>=256)
{
new_write = 0;
}
if(new_write==hdev->HCI_tx_buffer_read)
{
hdev->HCI_tx_buffer_status=HCI_TX_BUFF_FULL;
return HCI_TX_BUFF_FULL;
}
hdev->HCI_tx_buffer[hdev->HCI_tx_buffer_write]=ch;
hdev->HCI_tx_buffer_write=new_write;
return HCI_TX_BUFF_DATA;
}
__inline unsigned char HCI_Get_char(struct hci_dev *hdev)
{
unsigned char data;
if(hdev->HCI_tx_buffer_read != hdev->HCI_tx_buffer_write)
{
data = hdev->HCI_tx_buffer[hdev->HCI_tx_buffer_read++];
if(hdev->HCI_tx_buffer_read==256)
{
hdev->HCI_tx_buffer_read=0;
}
if(hdev->HCI_tx_buffer_read==hdev->HCI_tx_buffer_write)
{
hdev->HCI_tx_buffer_status = HCI_TX_BUFF_EMPTY;
}else
{
hdev->HCI_tx_buffer_status = HCI_TX_BUFF_DATA;
}
}
return data;
}
__inline void __bt_print_to_sdc(struct hci_dev *hdev)
{
unsigned char ch;
while(hdev->HCI_tx_buffer_read != hdev->HCI_tx_buffer_write)
{
ch = HCI_Get_char(hdev);
#ifdef DEBUG
printf("%x ",ch);
#else
SDC_Put_Char(ch, hdev->port);
#endif
// hdev->HCI_tx_buffer_read++;
}
}
/*
********************************************************************************
* 延时
* 功 能:延时
********************************************************************************
*/
void __delay(int counter)
{
int i;
for(i=0;i<5000*counter;i++)
{}
}
/*
__inline void hci_req_complete(struct hci_dev *hdev, int result)
{
if (hdev->req_status == HCI_REQ_PEND) {
hdev->req_result = result;
hdev->req_status = HCI_REQ_DONE;
}
}
*/
/*
********************************************************************************
HCI Commands
********************************************************************************
*/
/*
***********************************************************************************************************
* 发送命令
* 功 能:蓝牙发送命令是以小模式来发送的,按照byte为单位,从lsb开始发送,msb发送在最后。
* 这个函数把要发送的命令及其参数按照小模式的格式发再HCI_Tx_buff里面,等待发送。
***********************************************************************************************************
*/
void hci_send_cmd(struct hci_dev *hdev,UINT16 ogf,UINT8 ocf,UINT32 plen,void *param)
{
int i;
hci_command_hdr hc;
//int len = 1 + HCI_COMMAND_HDR_SIZE + plen;//add the pkt indicator
hc.opcode = cmd_opcode_pack(ogf,ocf); /* remember to invert the order*/
hc.plen = plen;
//tx the packet indicator
HCI_Put_char(hdev,(unsigned char)HCI_COMMAND_PKT);
//tx the command hdr
for(i=0;i<HCI_COMMAND_HDR_SIZE;i++)
HCI_Put_char(hdev,*((unsigned char*)&hc+i));
//put the parameter
for(i=0;i<plen;i++)
HCI_Put_char(hdev,*((char*)param+i));
}
/*
***********************************************************************************************************
* hci_inquiry
* 功 能:发送inquiry命令,查询周围的蓝牙设备
***********************************************************************************************************
*/
void hci_inq_req(struct hci_dev *hdev)
{
inquiry_cp *ic;
/* Start Inquiry */
//hdev->req_status = HCI_REQ_PEND;
ic = &(hdev->ic);
hci_send_cmd(hdev, OGF_LINK_CTL, OCF_INQUIRY, INQUIRY_CP_SIZE, (void*)ic);
}
/*
***********************************************************************************************************
* hci_conn_add
* 功 能:将与指定的蓝牙地址的蓝牙设备的连接信息添加到hci_conn_array[4]里面
***********************************************************************************************************
*/
void hci_conn_add(struct hci_dev *hdev,UINT16 handle,UINT8 type,char *dst)
{
int i;
if(hdev->hci_connection.hci_c_info.handle==handle||hdev->hci_connection.hci_c_info.handle==NULL)
{
hdev->hci_connection.hci_c_info.handle=handle;
__bt_mem_cpy((void*)hdev->hci_connection.hci_c_info.dst,(void*)dst,6);
if(type)//acl link
{
hdev->hci_connection.acl_conn_info.link_type = type;
hdev->hci_connection.acl_conn_info.acl_link_flags = 1;
hdev->hci_connection.sco_conn_info[0].sco_link_flags = 0;
hdev->hci_connection.sco_conn_info[1].sco_link_flags = 0;
}
else{
for(i=0;i<2;i++)
if(!(hdev->hci_connection.sco_conn_info[i].sco_link_flags))
{
hdev->hci_connection.sco_conn_info[i].link_type = type;
hdev->hci_connection.sco_conn_info[i].sco_link_flags = 1;
return;
}
}
}
}
void hci_conn_del(struct hci_dev *hdev)
{
hdev->hci_connection.hci_c_info.handle=NULL;
hdev->hci_connection.sco_conn_info[0].sco_link_flags = 0;
hdev->hci_connection.sco_conn_info[1].sco_link_flags = 0;
}
/*
***********************************************************************************************************
* hci create connection
* 功 能:发送创建连接命令命令,与指定蓝牙地址的蓝牙设备建立连接
***********************************************************************************************************
*/
//hci command:hci create connection
int hci_create_connect(struct hci_dev *hdev,char *bdaddr)
{
create_conn_cp cc;
UINT16 clock_offset;
cc.pscan_rep_mode = hdev->hci_inquiry_info.pscan_rep_mode;
cc.pscan_mode = hdev->hci_inquiry_info.pscan_mode;
clock_offset = (hdev->hci_inquiry_info.clock_offset) & 0x8000;
__bt_mem_cpy((void*)&cc.bdaddr,(void*)bdaddr,6);
cc.pkt_type = hdev->hci_device_info.pkt_type;
cc.clock_offset = clock_offset;
cc.role_switch = (hdev->hci_device_info.features[0] & LMP_RSWITCH) ? 0x01:0x00;
hci_send_cmd(hdev,OGF_LINK_CTL,OCF_CREATE_CONN,CREATE_CONN_CP_SIZE,(void*)&cc);
return 0;
}
/*
***********************************************************************************************************
* hci disconnect
* 功 能:发送断开连接命令命令,并给出断开连接的原因
***********************************************************************************************************
*/
int hci_disconnect(struct hci_dev *hdev,UINT8 reason)
{
disconnect_cp dc;
dc.handle = (UINT16)(hdev->hci_connection.hci_c_info.handle);
dc.reason = reason;
hci_send_cmd(hdev,OGF_LINK_CTL,OCF_DISCONNECT,DISCONNECT_CP_SIZE,(void*)&dc);
return 0;
}
/*
***********************************************************************************************************
* add sco connection
* 功 能:发送添加sco连接命令,创建sco连接
***********************************************************************************************************
*/
int hci_add_sco_conn(struct hci_dev *hdev)
{
add_sco_con_cp asc;
asc.handle = (UINT16)(hdev->hci_connection.hci_c_info.handle);
asc.pkt_type = hdev->hci_device_info.pkt_type;
hci_send_cmd(hdev,OGF_LINK_CTL,OCF_ADD_SCO_CONN,ADD_SCO_CONN_SIZE,(void*)&asc);
return 0;
}
/*
***********************************************************************************************************
* hci accept connnection requst
* 功 能:发送接收远方蓝牙设备建立连接命令
***********************************************************************************************************
*/
int hci_accept_conn_req(struct hci_dev *hdev)
{
accept_conn_req_cp acr;
hdev->req_status = HCI_REQ_PEND;
__bt_mem_cpy((void*)(acr.bdaddr),(void*)(hdev->hci_inquiry_info.bdaddr),6);//
acr.role = (hdev->hci_device_info.features[0] & LMP_RSWITCH) ? 0x01:0x00;
hci_send_cmd(hdev,OGF_LINK_CTL,OCF_ACCEPT_CONN_REQ,ACCEPT_CONN_REQ_CP_SIZE,(void*)&acr);
return 0;
}
/*
***********************************************************************************************************
* 拒绝建立连接请求
* 功 能:发送拒绝建立连接请求命令
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -