📄 bt_ip_lap.c
字号:
//p = pbuf_alloc(PBUF_RAW, sizeof("ATZ\r")-1, PBUF_RAM);
//((u8_t *)p->payload) = "ATZ\r";
p = pbuf_alloc(PBUF_RAW, sizeof("AT\r"), PBUF_RAM);
((u8_t *)p->payload) = "AT\r";
at_state = 0;
if(rfcomm_cl(pcb)) {
rfcomm_uih_credits(pcb, 6, p);
} else {
rfcomm_uih(pcb, rfcomm_cn(pcb), p);
}
pbuf_free(p);
} else {
/* Establish a PPP connection */
if((ppppcb = ppp_new(pcb)) == NULL) {
LWIP_DEBUGF(BT_IP_DEBUG, ("rfcomm_msc_rsp: Could not alloc PPP pcb\n"));
return ERR_MEM;
}
/* Add PPP network interface to lwIP and initialize NAT */
gw.addr = 0;
ipaddr.addr = 0;
IP4_ADDR(&netmask, 255,255,255,0);
netif = netif_add(&ipaddr, &netmask, &gw, NULL, bluetoothif_init, nat_input);
netif_set_default(netif);
ppp_netif(ppppcb, netif);
rfcomm_recv(pcb, ppp_input);
ppp_disconnected(ppppcb, ppp_is_disconnected);
return ppp_connect(ppppcb, ppp_connected);
}
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("rfcomm_connected. Connection attempt failed CN = %d\n", rfcomm_cn(pcb)));
l2cap_close(pcb->l2cappcb);
rfcomm_close(pcb);
bt_ip_start();
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* sdp_attributes_recv():
*
* Can be used as a callback by SDP when a response to a service attribute request or
* a service search attribute request was received.
* Disconnects the L2CAP SDP channel and connects to the RFCOMM one.
* If no RFCOMM channel was found it initializes a search for other devices.
*/
/*-----------------------------------------------------------------------------------*/
void
sdp_attributes_recv(void *arg, struct sdp_pcb *sdppcb, u16_t attribl_bc, struct pbuf *p)
{
struct l2cap_pcb *l2cappcb;
l2ca_disconnect_req(sdppcb->l2cappcb, l2cap_disconnected_cfm);
/* Get the RFCOMM channel identifier from the protocol descriptor list */
if((bt_ip_state.cn = get_rfcomm_cn(attribl_bc, p)) != 0) {
if((l2cappcb = l2cap_new()) == NULL) {
LWIP_DEBUGF(BT_IP_DEBUG, ("sdp_attributes_recv: Could not alloc L2CAP pcb\n"));
return;
}
LWIP_DEBUGF(BT_IP_DEBUG, ("sdp_attributes_recv: RFCOMM channel: %d\n", bt_ip_state.cn));
if(bt_ip_state.profile == DUN_PROFILE) {
l2ca_connect_req(l2cappcb, &(sdppcb->l2cappcb->remote_bdaddr), RFCOMM_PSM, 0, l2cap_connected);
} else {
l2ca_connect_req(l2cappcb, &(sdppcb->l2cappcb->remote_bdaddr), RFCOMM_PSM, HCI_ALLOW_ROLE_SWITCH, l2cap_connected);
}
} else {
bt_ip_start();
}
sdp_free(sdppcb);
}
/*-----------------------------------------------------------------------------------*/
/*
* l2cap_connected():
*
* Called by L2CAP when a connection response was received.
* Sends a L2CAP configuration request.
* Initializes a search for other devices if the connection attempt failed.
*/
/*-----------------------------------------------------------------------------------*/
err_t
l2cap_connected(void *arg, struct l2cap_pcb *l2cappcb, u16_t result, u16_t status)
{
struct sdp_pcb *sdppcb;
struct rfcomm_pcb *rfcommpcb;
u8_t ssp[] = {0x35, 0x03, 0x19, 0x11, 0x02}; /* Service search pattern with LAP UUID is default */
err_t ret;
u8_t attrids[] = {0x35, 0x03, 0x09, 0x00, 0x04}; /* Attribute IDs to search for in data element
sequence form */
if(result == L2CAP_CONN_SUCCESS) {
LWIP_DEBUGF(BT_IP_DEBUG, ("l2cap_connected: L2CAP connected pcb->state = %d\n", l2cappcb->state));
/* Tell L2CAP that we wish to be informed of a disconnection request */
l2cap_disconnect_ind(l2cappcb, l2cap_disconnected_ind);
switch(l2cap_psm(l2cappcb)) {
case SDP_PSM:
LWIP_DEBUGF(BT_IP_DEBUG, ("l2cap_connected: SDP L2CAP configured. Result = %d\n", result));
if(bt_ip_state.profile == DUN_PROFILE) {
LWIP_DEBUGF(BT_IP_DEBUG, ("l2cap_connected: Using DUN profile\n"));
ssp[4] = 0x03; /* Change service search pattern to contain DUN UUID */
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("l2cap_connected: Using LAP profile\n"));
}
if((sdppcb = sdp_new(l2cappcb)) == NULL) {
LWIP_DEBUGF(BT_IP_DEBUG, ("l2cap_connected: Failed to create a SDP PCB\n"));
return ERR_MEM;
}
l2cap_recv(l2cappcb, sdp_recv);
ret = sdp_service_search_attrib_req(sdppcb, 0xFFFF, ssp, sizeof(ssp), attrids, sizeof(attrids),
sdp_attributes_recv);
return ret;
case RFCOMM_PSM:
LWIP_DEBUGF(BT_IP_DEBUG, ("l2cap_connected: RFCOMM L2CAP configured. Result = %d CN = %d\n", result, bt_ip_state.cn));
l2cap_recv(l2cappcb, rfcomm_input);
if((rfcommpcb = rfcomm_new(l2cappcb)) == NULL) {
LWIP_DEBUGF(BT_IP_DEBUG, ("l2cap_connected: Failed to create a RFCOMM PCB\n"));
return ERR_MEM;
}
hci_link_key_not(link_key_not); /* Set function to be called if a new link key is created */
return rfcomm_connect(rfcommpcb, bt_ip_state.cn, rfcomm_connected); /* Connect with DLCI 0 */
default:
return ERR_VAL;
}
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("l2cap_connected: L2CAP not connected. Redo inquiry\n"));
l2cap_close(l2cappcb);
bt_ip_start();
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* inquiry_complete():
*
* Called by HCI when a inquiry complete event was received.
* Connects to the first device in the list.
* Initializes a search for other devices if the inquiry failed.
*/
/*-----------------------------------------------------------------------------------*/
err_t
inquiry_complete(void *arg, struct hci_pcb *pcb, struct hci_inq_res *ires, u16_t result)
{
struct l2cap_pcb *l2cappcb;
if(result == HCI_SUCCESS) {
LWIP_DEBUGF(BT_IP_DEBUG, ("successful Inquiry\n"));
if(ires != NULL) {
LWIP_DEBUGF(BT_IP_DEBUG, ("Initiate L2CAP connection\n"));
LWIP_DEBUGF(BT_IP_DEBUG, ("ires->psrm %d\n ires->psm %d\n ires->co %d\n", ires->psrm, ires->psm, ires->co));
LWIP_DEBUGF(BT_IP_DEBUG, ("ires->bdaddr 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", ires->bdaddr.addr[5], ires->bdaddr.addr[4], ires->bdaddr.addr[3], ires->bdaddr.addr[2], ires->bdaddr.addr[1], ires->bdaddr.addr[0]));
if((ires->cod[1] & 0x1F) == 0x03) {
bt_ip_state.profile = LAP_PROFILE;
} else {
bt_ip_state.profile = DUN_PROFILE;
}
if((l2cappcb = l2cap_new()) == NULL) {
LWIP_DEBUGF(BT_IP_DEBUG, ("inquiry_complete: Could not alloc L2CAP pcb\n"));
return ERR_MEM;
}
if(bt_ip_state.profile == DUN_PROFILE) {
l2ca_connect_req(l2cappcb, &(ires->bdaddr), SDP_PSM, 0, l2cap_connected);
} else {
l2ca_connect_req(l2cappcb, &(ires->bdaddr), SDP_PSM, HCI_ALLOW_ROLE_SWITCH, l2cap_connected);
}
} else {
hci_inquiry(0x009E8B33, 0x04, 0x01, inquiry_complete);
}
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("Unsuccessful Inquiry.\n"));
hci_inquiry(0x009E8B33, 0x04, 0x01, inquiry_complete);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* acl_wpl_complete():
*
* Called by HCI when a successful write link policy settings complete event was
* received.
*/
/*-----------------------------------------------------------------------------------*/
err_t
acl_wpl_complete(void *arg, struct bd_addr *bdaddr)
{
hci_sniff_mode(bdaddr, 200, 100, 10, 10);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* acl_conn_complete():
*
* Called by HCI when a connection complete event was received.
*/
/*-----------------------------------------------------------------------------------*/
err_t
acl_conn_complete(void *arg, struct bd_addr *bdaddr)
{
//hci_wlp_complete(acl_wpl_complete);
//hci_write_link_policy_settings(bdaddr, 0x000F);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* read_bdaddr_complete():
*
* Called by HCI when a read local bluetooth device address complete event was received.
*/
/*-----------------------------------------------------------------------------------*/
err_t
read_bdaddr_complete(void *arg, struct bd_addr *bdaddr)
{
memcpy(&(bt_ip_state.bdaddr), bdaddr, 6);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* command_complete():
*
* Called by HCI when an issued command has completed during the initialization of the
* host controller.
* Initializes a search for other devices when host controller initialization is
* completed.
*/
/*-----------------------------------------------------------------------------------*/
err_t
command_complete(void *arg, struct hci_pcb *pcb, u8_t ogf, u8_t ocf, u8_t result)
{
u8_t cod_lap_dun[] = {0x00,0x02,0x00,0x00,0x1E,0x00};
u8_t cod_lap[] = {0x00,0x03,0x00};
u8_t devname[] = {'E','I','S','L','A','B',' ','0','0','0',0};
u8_t n1, n2, n3;
switch(ogf) {
case HCI_INFO_PARAM:
switch(ocf) {
case HCI_READ_BUFFER_SIZE:
if(result == HCI_SUCCESS) {
LWIP_DEBUGF(BT_IP_DEBUG, ("successful HCI_READ_BUFFER_SIZE.\n"));
hci_read_bd_addr(read_bdaddr_complete);
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("Unsuccessful HCI_READ_BUFFER_SIZE.\n"));
return ERR_CONN;
}
break;
case HCI_READ_BD_ADDR:
if(result == HCI_SUCCESS) {
LWIP_DEBUGF(BT_IP_DEBUG, ("successful HCI_READ_BD_ADDR.\n"));
hci_set_event_filter(0x01, 0x01, cod_lap_dun); /* Report only devices with a specific type of CoD */
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("Unsuccessful HCI_READ_BD_ADDR.\n"));
return ERR_CONN;
}
break;
default:
LWIP_DEBUGF(BT_IP_DEBUG, ("Unknown HCI_INFO_PARAM command complete event\n"));
break;
}
break;
case HCI_HC_BB_OGF:
switch(ocf) {
case HCI_RESET:
if(result == HCI_SUCCESS) {
LWIP_DEBUGF(BT_IP_DEBUG, ("successful HCI_RESET.\n"));
hci_read_buffer_size();
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("Unsuccessful HCI_RESET.\n"));
return ERR_CONN;
}
break;
case HCI_WRITE_SCAN_ENABLE:
if(result == HCI_SUCCESS) {
LWIP_DEBUGF(BT_IP_DEBUG, ("successful HCI_WRITE_SCAN_ENABLE.\n"));
hci_cmd_complete(NULL); /* Initialization done, don't come back */
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("Unsuccessful HCI_WRITE_SCAN_ENABLE.\n"));
return ERR_CONN;
}
break;
case HCI_SET_EVENT_FILTER:
if(result == HCI_SUCCESS) {
LWIP_DEBUGF(BT_IP_DEBUG, ("successful HCI_SET_EVENT_FILTER.\n"));
if(bt_ip_state.btctrl == 0) {
hci_write_cod(cod_lap); /* */
bt_ip_state.btctrl = 1;
} else {
hci_write_scan_enable(0x03); /* Inquiry and page scan enabled */
}
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("Unsuccessful HCI_SET_EVENT_FILTER.\n"));
return ERR_CONN;
}
break;
case HCI_CHANGE_LOCAL_NAME:
if(result == HCI_SUCCESS) {
LWIP_DEBUGF(BT_IP_DEBUG, ("Successful HCI_CHANGE_LOCAL_NAME.\n"));
hci_write_page_timeout(0x4000); /* 10.24s */
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("Unsuccessful HCI_CHANGE_LOCAL_NAME.\n"));
return ERR_CONN;
}
break;
case HCI_WRITE_COD:
if(result == HCI_SUCCESS) {
LWIP_DEBUGF(BT_IP_DEBUG, ("Successful HCI_WRITE_COD.\n"));
n1 = (u8_t)(bt_ip_state.bdaddr.addr[0] / 100);
n2 = (u8_t)(bt_ip_state.bdaddr.addr[0] / 10) - n1 * 10;
n3 = bt_ip_state.bdaddr.addr[0] - n1 * 100 - n2 * 10;
devname[7] = '0' + n1;
devname[8] = '0' + n2;
devname[9] = '0' + n3;
hci_change_local_name(devname, sizeof(devname));
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("Unsuccessful HCI_WRITE_COD.\n"));
return ERR_CONN;
}
break;
case HCI_WRITE_PAGE_TIMEOUT:
if(result == HCI_SUCCESS) {
LWIP_DEBUGF(BT_IP_DEBUG, ("successful HCI_WRITE_PAGE_TIMEOUT.\n"));
hci_cmd_complete(NULL); /* Initialization done, don't come back */
hci_connection_complete(acl_conn_complete);
LWIP_DEBUGF(BT_IP_DEBUG, ("Initialization done.\n"));
LWIP_DEBUGF(BT_IP_DEBUG, ("Discover other Bluetooth devices.\n"));
hci_inquiry(0x009E8B33, 0x04, 0x01, inquiry_complete); //FAILED????
} else {
LWIP_DEBUGF(BT_IP_DEBUG, ("Unsuccessful HCI_WRITE_PAGE_TIMEOUT.\n"));
return ERR_CONN;
}
break;
default:
LWIP_DEBUGF(BT_IP_DEBUG, ("Unknown HCI_HC_BB_OGF command complete event\n"));
break;
}
break;
default:
LWIP_DEBUGF(BT_IP_DEBUG, ("Unknown command complete event. OGF = 0x%x OCF = 0x%x\n", ogf, ocf));
break;
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -