📄 hci.c
字号:
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_W_SCAN_EN_OCF, HCI_HC_BB_OGF, HCI_W_SCAN_EN_PLEN);
/* Assembling cmd prameters */
((u8_t *)p->payload)[4] = scan_enable;
phybusif_output(p, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* hci_write_cod():
*
* Write the value for the Class_of_Device parameter, which is used to indicate its
* capabilities to other devices.
*/
/*-----------------------------------------------------------------------------------*/
err_t
hci_write_cod(u8_t *cod)
{
struct pbuf *p;
if((p = pbuf_alloc(PBUF_RAW, HCI_W_COD_PLEN, PBUF_RAM)) == NULL) {
LWIP_DEBUGF(HCI_DEBUG, ("hci_write_cod: Could not allocate memory for pbuf\n"));
return ERR_MEM;
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_W_COD_OCF, HCI_HC_BB_OGF, HCI_W_COD_PLEN);
/* Assembling cmd prameters */
memcpy(((u8_t *)p->payload)+4, cod, 3);
phybusif_output(p, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* hci_set_hc_to_h_fc():
*
* Used by the Host to turn flow control on or off in the direction from the Host
* Controller to the Host.
*/
/*-----------------------------------------------------------------------------------*/
err_t
hci_set_hc_to_h_fc(void)
{
struct pbuf *p;
if((p = pbuf_alloc(PBUF_RAW, HCI_SET_HC_TO_H_FC_PLEN, PBUF_RAM)) == NULL) {
LWIP_DEBUGF(HCI_DEBUG, ("hci_set_hc_to_h_fc: Could not allocate memory for pbuf\n"));
return ERR_MEM;
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_SET_HC_TO_H_FC_OCF, HCI_HC_BB_OGF, HCI_SET_HC_TO_H_FC_PLEN);
/* Assembling cmd prameters */
((u8_t *)p->payload)[4] = 0x01; /* Flow control on for HCI ACL Data Packets and off for HCI
SCO Data Packets in direction from Host Controller to
Host */
phybusif_output(p, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* hci_host_buffer_size():
*
* Used by the Host to notify the Host Controller about the maximum size of the data
* portion of HCI ACL Data Packets sent from the Host Controller to the Host.
*/
/*-----------------------------------------------------------------------------------*/
err_t
hci_host_buffer_size(void)
{
struct pbuf *p;
if((p = pbuf_alloc(PBUF_RAW, HCI_H_BUF_SIZE_PLEN, PBUF_RAM)) == NULL) {
LWIP_DEBUGF(HCI_DEBUG, ("hci_host_buffer_size: Could not allocate memory for pbuf\n"));
return ERR_MEM;
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_H_BUF_SIZE_OCF, HCI_HC_BB_OGF, HCI_H_BUF_SIZE_PLEN);
((u16_t *)p->payload)[2] = HCI_HOST_ACL_MAX_LEN; /* Host ACL data packet maximum length */
((u8_t *)p->payload)[6] = 255; /* Host SCO Data Packet Length */
*((u16_t *)(((u8_t *)p->payload)+7)) = HCI_HOST_MAX_NUM_ACL; /* Host max total num ACL data packets */
((u16_t *)p->payload)[4] = 1; /* Host Total Num SCO Data Packets */
phybusif_output(p, p->tot_len);
pbuf_free(p);
pcb->host_num_acl = HCI_HOST_MAX_NUM_ACL;
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* hci_host_num_comp_packets():
*
* Used by the Host to indicate to the Host Controller the number of HCI Data Packets
* that have been completed for each Connection Handle since the previous
* Host_Number_Of_Completed_Packets command was sent to the Host Controller.
*/
/*-----------------------------------------------------------------------------------*/
err_t
hci_host_num_comp_packets(u16_t conhdl, u16_t num_complete)
{
struct pbuf *p;
if((p = pbuf_alloc(PBUF_RAW, HCI_H_NUM_COMPL_PLEN, PBUF_RAM)) == NULL) {
LWIP_DEBUGF(HCI_DEBUG, ("hci_host_num_comp_packets: Could not allocate memory for pbuf\n"));
return ERR_MEM;
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_H_NUM_COMPL_OCF, HCI_HC_BB_OGF, HCI_H_NUM_COMPL_PLEN);
((u16_t *)p->payload)[2] = conhdl;
((u16_t *)p->payload)[3] = num_complete; /* Number of completed acl packets */
phybusif_output(p, p->tot_len);
pbuf_free(p);
pcb->host_num_acl += num_complete;
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* hci_read_buffer_size():
*
* Used to read the maximum size of the data portion of HCI ACL packets sent from the
* Host to the Host Controller.
*/
/*-----------------------------------------------------------------------------------*/
err_t
hci_read_buffer_size(void)
{
struct pbuf *p;
if((p = pbuf_alloc(PBUF_RAW, HCI_R_BUF_SIZE_PLEN, PBUF_RAM)) == NULL) {
LWIP_DEBUGF(HCI_DEBUG, ("hci_read_buffer_size: Could not allocate memory for pbuf\n"));
return ERR_MEM;
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_R_BUF_SIZE_OCF, HCI_INFO_PARAM_OGF, HCI_R_BUF_SIZE_PLEN);
/* Assembling cmd prameters */
phybusif_output(p, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* hci_read_bd_addr():
*
* Used to retreive the Bluetooth address of the host controller.
*/
/*-----------------------------------------------------------------------------------*/
err_t
hci_read_bd_addr(err_t (* rbd_complete)(void *arg, struct bd_addr *bdaddr))
{
struct pbuf *p;
pcb->rbd_complete = rbd_complete;
if((p = pbuf_alloc(PBUF_RAW, HCI_R_BD_ADDR_PLEN, PBUF_RAM)) == NULL) {
LWIP_DEBUGF(HCI_DEBUG, ("hci_read_buffer_size: Could not allocate memory for pbuf\n"));
return ERR_MEM;
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_READ_BD_ADDR, HCI_INFO_PARAM_OGF, HCI_R_BD_ADDR_PLEN);
/* Assembling cmd prameters */
phybusif_output(p, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* lp_write_flush_timeout():
*
* Called by L2CAP to set the flush timeout for the ACL link.
*/
/*-----------------------------------------------------------------------------------*/
err_t
lp_write_flush_timeout(struct bd_addr *bdaddr, u16_t flushto)
{
struct hci_link *link;
struct pbuf *p;
/* Check if an ACL connection exists */
link = hci_get_link(bdaddr);
if(link == NULL) {
LWIP_DEBUGF(HCI_DEBUG, ("lp_write_flush_timeout: ACL connection does not exist\n"));
return ERR_CONN;
}
if((p = pbuf_alloc(PBUF_TRANSPORT, HCI_W_FLUSHTO_PLEN, PBUF_RAM)) == NULL) { /* Alloc len of packet */
LWIP_DEBUGF(HCI_DEBUG, ("lp_write_flush_timeout: Could not allocate memory for pbuf\n"));
return ERR_MEM;
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_W_FLUSHTO, HCI_HC_BB_OGF, HCI_W_FLUSHTO_PLEN);
/* Assembling cmd prameters */
((u16_t *)p->payload)[2] = link->conhdl;
((u16_t *)p->payload)[3] = flushto;
phybusif_output(p, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* lp_connect_req():
*
* Called by L2CAP to cause the Link Manager to create a connection to the
* Bluetooth device with the BD_ADDR specified by the command parameters.
*/
/*-----------------------------------------------------------------------------------*/
err_t
lp_connect_req(struct bd_addr *bdaddr, u8_t allow_role_switch)
{
u8_t page_scan_repetition_mode, page_scan_mode;
u16_t clock_offset;
struct pbuf *p;
struct hci_link *link = hci_new();
struct hci_inq_res *inqres;
if(link == NULL) {
LWIP_DEBUGF(HCI_DEBUG, ("lp_connect_req: Could not allocate memory for link\n"));
return ERR_MEM; /* Could not allocate memory for link */
}
bd_addr_set(&(link->bdaddr), bdaddr);
HCI_REG(&(hci_active_links), link);
/* Check if module has been discovered in a recent inquiry */
for(inqres = pcb->ires; inqres != NULL; inqres = inqres->next) {
if(bd_addr_cmp(&inqres->bdaddr, bdaddr)) {
page_scan_repetition_mode = inqres->psrm;
page_scan_mode = inqres->psm;
clock_offset = inqres->co;
break;
}
}
if(inqres == NULL) {
/* No information on parameters from an inquiry. Using default values */
page_scan_repetition_mode = 0x01; /* Assuming worst case: time between
successive page scans starting
<= 2.56s */
page_scan_mode = 0x00; /* Assumes the device uses mandatory scanning, most
devices use this. If no conn is established, try
again w this parm set to optional page scanning */
clock_offset = 0x00; /* If the device was not found in a recent inquiry
this information is irrelevant */
}
if((p = pbuf_alloc(PBUF_RAW, HCI_CREATE_CONN_PLEN, PBUF_RAM)) == NULL) {
LWIP_DEBUGF(HCI_DEBUG, ("lp_connect_req: Could not allocate memory for pbuf\n"));
return ERR_MEM; /* Could not allocate memory for pbuf */
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_CREATE_CONN_OCF, HCI_LINK_CTRL_OGF, HCI_CREATE_CONN_PLEN);
/* Assembling cmd prameters */
memcpy(((u8_t *)p->payload)+4, bdaddr->addr, 6);
((u16_t *)p->payload)[5] = HCI_PACKET_TYPE;
((u8_t *)p->payload)[12] = page_scan_repetition_mode;
((u8_t *)p->payload)[13] = page_scan_mode;
((u16_t *)p->payload)[7] = clock_offset;
((u8_t *)p->payload)[16] = allow_role_switch;
phybusif_output(p, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* lp_acl_write():
*
* Called by L2CAP to send data to the Host Controller that will be transfered over
* the ACL link from there.
*/
/*-----------------------------------------------------------------------------------*/
err_t
lp_acl_write(struct bd_addr *bdaddr, struct pbuf *p, u16_t len, u8_t pb)
{
struct hci_link *link;
static struct hci_acl_hdr *aclhdr;
struct pbuf *q;
/* Check if an ACL connection exists */
link = hci_get_link(bdaddr);
if(link == NULL) {
LWIP_DEBUGF(HCI_DEBUG, ("lp_acl_write: ACL connection does not exist\n"));
return ERR_CONN;
}
LWIP_DEBUGF(HCI_DEBUG, ("lp_acl_write: HC num ACL %d\n", pcb->hc_num_acl));
if(pcb->hc_num_acl == 0) {
LWIP_DEBUGF(HCI_DEBUG, ("lp_acl_write: HC out of buffer space\n"));
#if HCI_FLOW_QUEUEING
if(p != NULL) {
/* Packet can be queued? */
if(link->p != NULL) {
LWIP_DEBUGF(HCI_DEBUG, ("lp_acl_write: Host buffer full. Dropped packet\n"));
return ERR_OK; /* Drop packet */
} else {
/* Copy PBUF_REF referenced payloads into PBUF_RAM */
p = pbuf_take(p);
/* Remember pbuf to queue, if any */
link->p = p;
link->len = len;
link->pb = pb;
/* Pbufs are queued, increase the reference count */
pbuf_ref(p);
LWIP_DEBUGF(HCI_DEBUG, ("lp_acl_write: Host queued packet %p\n", (void *)p));
}
}
#else
LWIP_DEBUGF(HCI_DEBUG, ("lp_acl_write: Dropped packet\n"));
#endif
return ERR_OK;
}
if((q = pbuf_alloc(PBUF_RAW, 1+HCI_ACL_HDR_LEN, PBUF_RAM)) == NULL) {
/* Could not allocate memory for pbuf */
LWIP_DEBUGF(HCI_DEBUG, ("lp_acl_write: Could not allocate memory for pbuf\n"));
return ERR_MEM;
}
pbuf_chain(q, p);
((u8_t*)q->payload)[0] = HCI_ACL_DATA_PACKET;
aclhdr = (void *)(((u8_t*)q->payload)+1);
aclhdr->conhdl_pb_bc = link->conhdl; /* Received from connection complete event */
aclhdr->conhdl_pb_bc |= pb << 12; /* Packet boundary flag */
aclhdr->conhdl_pb_bc &= 0x3FFF; /* Point-to-point */
aclhdr->len = len;
LWIP_DEBUGF(HCI_DEBUG, ("lp_acl_write: q->tot_len = %d aclhdr->len + q->len = %d\n", q->tot_len, aclhdr->len + q->len));
phybusif_output(q, aclhdr->len + q->len);
--pcb->hc_num_acl;
/* Free ACL header. Upper layers will handle rest of packet */
p = pbuf_dechain(q);
pbuf_free(q);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* lp_is_connected():
*
* Called by L2CAP to check if an active ACL connection exists for the specified
* Bluetooth address.
*/
/*-----------------------------------------------------------------------------------*/
u8_t
lp_is_connected(struct bd_addr *bdaddr)
{
struct hci_link *link;
link = hci_get_link(bdaddr);
if(link == NULL) {
return 0;
}
return 1;
}
/*-----------------------------------------------------------------------------------*/
/* lp_pdu_maxsize():
*
* Called by L2CAP to check the maxsize of the PDU. In this case it is the largest
* ACL packet that the Host Controller can buffer.
*/
/*-----------------------------------------------------------------------------------*/
u16_t
lp_pdu_maxsize(void)
{
return pcb->maxsize;
}
/*-----------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -