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

📄 hci.c

📁 蓝牙协议源代码 bluetooth stack for lwip
💻 C
📖 第 1 页 / 共 4 页
字号:
  }
  /* 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 + -