📄 bt_ip_dt.c
字号:
/*
* Copyright (c) 2003 EISLAB, Lulea University of Technology.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwBT Bluetooth stack.
*
* Author: Conny Ohult <conny@sm.luth.se>
*
*/
/*-----------------------------------------------------------------------------------*/
/* bt_ip_dt.c
*
* This is a control application that initialises a host controller and connects to a
* network as a DT through a DUN or LAP enabled device.
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/stats.h"
#include "lwip/ip.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "phybusif.h"
#include "netif/lwbt/lwbt_memp.h"
#include "netif/lwbt/hci.h"
#include "netif/lwbt/l2cap.h"
#include "netif/lwbt/sdp.h"
#include "netif/lwbt/rfcomm.h"
#include "netif/lwbt/ppp.h"
#include "apps/httpd.h"
#include "stdlib.h"
#define BT_IP_DEBUG DBG_ON /* Control debug messages */
enum bt_profile {
LAP_PROFILE, DUN_PROFILE
};
struct bt_state {
enum bt_profile profile;
struct tcp_pcb *tcppcb;
struct bd_addr bdaddr;
u8_t cn;
} bt_ip_state;
/* Forward declarations */
err_t rfcomm_connected(void *arg, struct rfcomm_pcb *tpcb, err_t err);
err_t l2cap_connected(void *arg, struct l2cap_pcb *pcb, u16_t result, u16_t status);
err_t inquiry_complete(void *arg, struct hci_pcb *pcb, struct hci_inq_res *ires, u16_t result);
err_t command_complete(void *arg, struct hci_pcb *pcb, u8_t ogf, u8_t ocf, u8_t result);
err_t pin_req(void *arg, struct bd_addr *bdaddr);
err_t http_accept(void *arg, struct tcp_pcb *pcb, err_t err);
static const u8_t lap_service_record[] = {
0x35, 0x8,
0x9, 0x0, 0x0, 0xa, 0x0, 0x0, 0xff, 0xff, /* Service record handle attribute */
0x35, 0x8,
0x9, 0x0, 0x1, 0x35, 0x3, 0x19, 0x11, 0x2, /* Service class ID list attribute */
0x35, 0x11,
0x9, 0x0, 0x4, 0x35, 0xc, 0x35, 0x3, 0x19, 0x1, 0x0, 0x35, 0x5, 0x19, 0x0, 0x3, 0x8, 0x1 /* Protocol descriptor list attribute */
};
u8_t bt_ip_netifn;
/*-----------------------------------------------------------------------------------*/
/*
* bt_ip_start():
*
* Called by the main application to initialize and connect to a network
*
*/
/*-----------------------------------------------------------------------------------*/
void
bt_ip_start(void)
{
hci_reset_all();
l2cap_reset_all();
sdp_reset_all();
rfcomm_reset_all();
ppp_reset_all();
LWIP_DEBUGF(BT_IP_DEBUG, ("bt_ip_start\n"));
hci_cmd_complete(command_complete);
hci_pin_req(pin_req);
bt_ip_state.tcppcb = NULL;
bt_ip_netifn = 0;
hci_reset();
}
/*-----------------------------------------------------------------------------------*/
/*
* bt_ip_tmr():
*
* Called by the main application to initialize and connect to a network
*
*/
/*-----------------------------------------------------------------------------------*/
void
bt_ip_tmr(void)
{
u8_t update_cmd[12];
update_cmd[0] = 1;
update_cmd[1] = 0;
update_cmd[2] = bt_ip_state.bdaddr.addr[5];
update_cmd[3] = bt_ip_state.bdaddr.addr[4];
update_cmd[4] = bt_ip_state.bdaddr.addr[3];
update_cmd[5] = bt_ip_state.bdaddr.addr[2];
update_cmd[6] = bt_ip_state.bdaddr.addr[1];
update_cmd[7] = bt_ip_state.bdaddr.addr[0];
update_cmd[8] = 0x00;
update_cmd[9] = 0x00;
update_cmd[10] = 0x00;
update_cmd[11] = 0x00;
LWIP_DEBUGF(BT_IP_DEBUG, ("bt_ip_tmr: Update cmd bd address: 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", update_cmd[2], update_cmd[3], update_cmd[4], update_cmd[5], update_cmd[6], update_cmd[7]));
if(bt_ip_state.tcppcb != NULL) {
tcp_write(bt_ip_state.tcppcb, &update_cmd, 12, 1);
}
}
/*-----------------------------------------------------------------------------------*/
/*
* ppp_is_disconnected():
*
* Called by PPP when the remote PPP protocol or upper layer was disconnected.
* Disconnects the IP layer.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
ppp_is_disconnected(void *arg, struct ppp_pcb *pcb, u16_t proto, err_t err)
{
//TODO: CHECK PROTOCOL
LWIP_DEBUGF(BT_IP_DEBUG, ("ppp_disconnected\n"));
ppp_close(pcb);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* rfcomm_disconnected():
*
* Called by RFCOMM when the remote RFCOMM protocol or upper layer was disconnected.
* Disconnects the PPP protocol.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
rfcomm_disconnected(void *arg, struct rfcomm_pcb *pcb, err_t err)
{
err_t ret = ERR_OK;
LWIP_DEBUGF(BT_IP_DEBUG, ("rfcomm_disconnected: CN = %d\n", rfcomm_cn(pcb)));
if(rfcomm_cn(pcb) != 0) {
ret = ppp_lp_disconnected(pcb);
}
rfcomm_close(pcb);
return ret;
}
/*-----------------------------------------------------------------------------------*/
/*
* l2cap_disconnected_ind():
*
* Called by L2CAP to indicate that remote L2CAP protocol disconnected.
* Disconnects the RFCOMM protocol and the ACL link before it initializes a search for
* other devices.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
l2cap_disconnected_ind(void *arg, struct l2cap_pcb *pcb, err_t err)
{
err_t ret = ERR_OK;
LWIP_DEBUGF(BT_IP_DEBUG, ("l2cap_disconnected_ind: L2CAP disconnected\n"));
if(pcb->psm == SDP_PSM) {
sdp_lp_disconnected(pcb);
l2cap_close(pcb);
} else if(pcb->psm == RFCOMM_PSM) {
ret = rfcomm_lp_disconnected(pcb);
/* We can do this since we know that we are the only channel on the ACL link. If ACL link already is
down we get an ERR_CONN returned */
hci_disconnect(&(pcb->remote_bdaddr), HCI_OTHER_END_TERMINATED_CONN_USER_ENDED);
l2cap_close(pcb);
bt_ip_start();
}
return ret;
}
/*-----------------------------------------------------------------------------------*/
/*
* bluetoothif_init():
*
* Called by lwIP to initialize the lwBT network interface.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
bluetoothif_init(struct netif *netif)
{
netif->name[0] = 'b';
netif->name[1] = '0' + bt_ip_netifn++;
netif->output = ppp_netif_output;
netif->state = NULL;
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_connected():
*
* Called by TCP when a connection has been established.
* Connects to a remote gateway and give the TCP connection to the HTTP server
* application
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
u8_t update_cmd[12];
LWIP_DEBUGF(BT_IP_DEBUG, ("tcp_connected\n"));
update_cmd[0] = 1;
update_cmd[1] = 0;
update_cmd[2] = bt_ip_state.bdaddr.addr[5];
update_cmd[3] = bt_ip_state.bdaddr.addr[4];
update_cmd[4] = bt_ip_state.bdaddr.addr[3];
update_cmd[5] = bt_ip_state.bdaddr.addr[2];
update_cmd[6] = bt_ip_state.bdaddr.addr[1];
update_cmd[7] = bt_ip_state.bdaddr.addr[0];
LWIP_DEBUGF(BT_IP_DEBUG, ("tcp_connected: bd address: 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", bt_ip_state.bdaddr.addr[0], bt_ip_state.bdaddr.addr[1], bt_ip_state.bdaddr.addr[2], bt_ip_state.bdaddr.addr[3], bt_ip_state.bdaddr.addr[4], bt_ip_state.bdaddr.addr[5]));
LWIP_DEBUGF(BT_IP_DEBUG, ("tcp_connected: Update cmd bd address: 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", update_cmd[2], update_cmd[3], update_cmd[4], update_cmd[5], update_cmd[6], update_cmd[7]));
update_cmd[8] = 0x00;
update_cmd[9] = 0x00;
update_cmd[10] = 0x00;
update_cmd[11] = 0x00;
tcp_write(pcb, &update_cmd, 12, 1);
LWIP_DEBUGF(BT_IP_DEBUG, ("tcp_connected: Update command sent\n"));
bt_ip_state.tcppcb = pcb;
return http_accept((void *)&(bt_ip_state.bdaddr), pcb, ERR_OK);
}
/*-----------------------------------------------------------------------------------*/
/*
* ppp_connected():
*
* Called by PPP when a LCP and IPCP connection has been established.
* Connects to a given TCP host.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
ppp_connected(void *arg, struct ppp_pcb *pcb, err_t err)
{
struct tcp_pcb *tcppcb;
struct ip_addr ipaddr;
LWIP_DEBUGF(BT_IP_DEBUG, ("ppp_connected: err = %d\n", err));
/* return ppp_echo(pcb, NULL); */
if(err != ERR_OK) {
netif_remove(pcb->bluetoothif);
pcb->bluetoothif = NULL;
//TODO: RESTART??
return ERR_OK;
}
tcppcb = tcp_new();
IP4_ADDR(&ipaddr, 130,240,45,234);
return tcp_connect(tcppcb, &ipaddr, 8989, tcp_connected);
}
/*-----------------------------------------------------------------------------------*/
/*
* at_input():
*
* Called by RFCOMM during the DUN profile GPRS connection attempt.
* When a GPRS connection is established, PPP is connected.
*
*/
/*-----------------------------------------------------------------------------------*/
u8_t at_state;
err_t
at_input(void *arg, struct rfcomm_pcb *pcb, struct pbuf *p, err_t err)
{
struct ppp_pcb *ppppcb;
struct ip_addr ipaddr, netmask, gw;
struct netif *netif;;
// u16_t i;
struct pbuf *q;
//for(q = p; q != NULL; q = q->next) {
// for(i = 0; i < q->len; ++i) {
// LWIP_DEBUGF(BT_IP_DEBUG, ("at_input: 0x%x\n",((u8_t *)p->payload)[i]));
// }
// LWIP_DEBUGF(BT_IP_DEBUG, ("*\n"));
//}
LWIP_DEBUGF(BT_IP_DEBUG, ("at_input: %s\n", ((u8_t *)p->payload)));
LWIP_DEBUGF(BT_IP_DEBUG, ("state == %d\n", at_state));
if(at_state == 0 && ((u8_t *)p->payload)[2] == 'O') {
//q = pbuf_alloc(PBUF_RAW, sizeof("AT&F\r")-1, PBUF_RAM);
//((u8_t *)q->payload) = "AT&F\r";
q = pbuf_alloc(PBUF_RAW, sizeof("ATE1\r"), PBUF_RAM);
((u8_t *)q->payload) = "ATE1\r";
if(rfcomm_cl(pcb)) {
rfcomm_uih_credits(pcb, 2, q);
} else {
rfcomm_uih(pcb, rfcomm_cn(pcb), q);
}
pbuf_free(q);
at_state = 1;
} else if(at_state == 1 && ((u8_t *)p->payload)[2] == 'O') {
q = pbuf_alloc(PBUF_RAW, sizeof("AT+cgdcont=1,\"IP\",\"online.telia.se\"\r"), PBUF_RAM);
((u8_t *)q->payload) = "AT+cgdcont=1,\"IP\",\"online.telia.se\"\r";
if(rfcomm_cl(pcb)) {
rfcomm_uih_credits(pcb, 2, q);
} else {
rfcomm_uih(pcb, rfcomm_cn(pcb), q);
}
pbuf_free(q);
at_state = 4;
} else if(at_state == 4 && ((u8_t *)p->payload)[2] == 'O') {
q = pbuf_alloc(PBUF_RAW, sizeof("ATD*99***1#\r"), PBUF_RAM);
((u8_t *)q->payload) = "ATD*99***1#\r";
if(rfcomm_cl(pcb)) {
rfcomm_uih_credits(pcb, 2, q);
} else {
rfcomm_uih(pcb, rfcomm_cn(pcb), q);
}
pbuf_free(q);
at_state = 5;
} else if(at_state == 5 && ((u8_t *)p->payload)[2] == 'C') {
at_state = 6;
/* 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 */
gw.addr = 0;
ipaddr.addr = 0;
IP4_ADDR(&netmask, 255,255,255,0);
netif = netif_add(&ipaddr, &netmask, &gw, NULL, bluetoothif_init, ip_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);
}
pbuf_free(p);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* pin_req():
*
* Called by HCI when a request for a PIN code has been received. A PIN code is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -